当前位置: 代码迷 >> J2SE >> 多线程有关问题(全部的分了)
  详细解决方案

多线程有关问题(全部的分了)

热度:25   发布时间:2016-04-23 20:34:26.0
多线程问题(全部的分了)
public class test1 {
public static void main(String[] args) {
myThread m1 = new myThread(1);
myThread m2 = new myThread(2);
        new Thread(m1).start();
        new Thread(m2).start();
    }
}
class myThread implements Runnable{
     static int i = 1;
     int k;
     myThread(int k){
         this.k = k;
     }
     synchronized public void run() {
         while(i <= 100){
             System.out.println(k + "线程:" + i);
             i++;
         }
     }
}

为什么输出结果不是一个线程执行完另一个线程一次也不执行直接程序结束而是两个线程交替执行?
myThread类不是有一个静态变量i吗?第一个线程执行的时候锁定了m1,第二个线程应该拿不到m2的锁了吧.
------解决方案--------------------
不知道你写这段代码想测试的是什么功能。不过明显,你对多线程理解不够深入。synchronized同步的是对象,你在程序中创建了两个对象,作为两个线程去运行。同步方法没有起到对这两个线程的同步作用,输出有可能是
1线程:1
1线程:2
2线程:1
2线程:3
输出了两个1!
------解决方案--------------------
1. 要执行synchronized声明的方法,必须要获得该方法所属的对象的锁。

class MyHandler implements Runnable{
    int i = 0;
    public synchronized void run() {  // 需要获得MyHandler的某个实例的锁,才能进入这个方法
        i++;
        System.out.println(i);
    }
}

可以这么理解,就是把synchronized声明的方法(不一定是run方法,还可以是其他的)想象为一个房间(资源),如果有2个人(线程)都想进去,那么必须要有这个房间的钥匙(获得资源,并关上房门,即加锁)。如果1个人进去了,锁上了门,那么另外一个人就只能等待。


MyHandler h1 = new MyHandler();
Thread t1 = new Thread(h1); 
Thread t2 = new Thread(h1);
t1.start(); // t1可能获得了h1这个资源,并加了锁
t2.start(); // t2 可能就只能等待了,因为他没有获得h1这个资源,无法加锁(锁门)


区别

MyHandler h1 = new MyHandler();
MyHandler h2 = new MyHandler();
Thread t1 = new Thread(h1); 
Thread t2 = new Thread(h2);
t1.start(); // t1可能获得了h1这个资源,并加了锁
t2.start(); // t2 也可能获得了h2这个资源,并加了锁(因为h1和h2是两个资源,互相独立,所以t1和t2都可以各玩儿各的)



2. 同步块其实也是相同的概念,不过比synchronized方法灵活一点(可以对任意的资源,不一定是拥有synchronized方法本身的这个对象)

class Foo{

}

class MyHandler implements Runnable{
    Foo foo = new Foo();
    int i = 0;
    public  void run() {  
        synchronized(foo){ // 需要获得foo这个实例的锁,才能进入synchronized块,执行i++这个操作
            i++;
        }
        System.out.println(i);
    }
}


3. 使用java concurrent api,加锁更好(高大上)

class MyHandler{
    private static Lock lock = new ReentrantLock();
    private int i = 0;
    
    public void hello(){
        lock.lock();  // 加锁,不再使用笨拙的synchronized
        try{
            i++;
            System.out.println(i);
        } finally{
            lock.unlock();  // 释放锁
        }
    }
}

------解决方案--------------------
synchronized public void run()  是对象锁,锁定的是当前实例(this)

楼主的想锁定Class ,可以把synchronized 加在静态方法上,这样就是楼主想要的结果了

另外。
楼主没发现自己这句话:第一个线程执行的时候锁定了m1,第二个线程应该拿不到m2的锁了吧. 
已经语无伦次了么。。。
锁定了m1,是肯定拿不到m1的啊 。。。
  相关解决方案