日期:2014-05-20  浏览次数:20675 次

java的锁机制,到底都能锁住啥?
Java code

package net.zjfly.javapractise;

public class TT implements Runnable {
    int b = 100;
    
    public synchronized void m1() throws Exception{
        b = 1000;                     //修改值
        Thread.sleep(5000);           //睡眠,腾出足够的时间让别人修改b
        System.out.println("m1:b = " + b);
    }
    
    public synchronized void m2() throws Exception {
        Thread.sleep(2500);         //睡眠,确保m1能现修改值
        b = 2000;             //修改值
    }
    
    public void run() {
        try {
            m1();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) throws Exception {
        TT tt = new TT();
        Thread t = new Thread(tt);
        t.start();
        tt.m2();
        Thread.sleep(6000);
        System.out.println("主方法b=:"+tt.b);
    }
}



示例代码,我怎么觉得不管m2上不上锁,结果都应该一样,问题是结果却是不一样。
毕竟时锁的不同的方法,最后的值应该是m2修改后的,可是给m2加上锁后似乎m2没有其作用。

------解决方案--------------------
锁和不锁当然是不一样的了
LZ只不过是不清楚线程的执行不是按顺序的,而是随机的,谁抢到CPU谁就执行
Java code
public static void main(String[] args) throws Exception {
        TT tt = new TT();
        Thread t = new Thread(tt);
        t.start(); //这里线程t虽然start了,但是不表示一定会立即执行,因为CPU是随机分配的
                      //所以线程t不一定能分配到CPU,如果分配不到CPU,就会不立刻执行
        tt.m2(); //所以,如果这个时候主线程还是占用着CPU就会先执行m2,
                   //那么最后的结果因为被m1修改了,所以感觉好像m2没效果
        Thread.sleep(6000);
        System.out.println("主方法b=:"+tt.b);
    }

------解决方案--------------------
你这样子当然没有用,那个tt.m2();就是一个普通方法调用!
就像tt.run();只是个普通的方法调用!
------解决方案--------------------
1) m2加锁时
虽然语句t.start()在tt.m2()之前,但正如1楼所说,线程虽然是起了,但不一定会立即分配到CPU,故
m2先获得锁,之后线程t执行时,发现锁已被方法m2锁住,故其等待,然后m2将b设置为2000后解锁,然后
主线程睡眠,此时m1立即获得锁然后将b设置为1000,然后是睡眠,醒后输出m1:b = 1000,然后主线程
睡醒后输出后一句。
2) m2不加锁
自己分析吧
------解决方案--------------------
锁主要是为了锁住资源,不让多个线程同时抢占一个资源,防止出错。
LZ去看些同步这方面的应该就会明白一些的。
------解决方案--------------------
探讨

不加锁的情况非常简单,就是不能完成同步了。。
问题是加锁后,照2楼的解释,结果是随机的。
我试了几次,次数也不少,貌似结果全是一致的。。

------解决方案--------------------
锁住鱼尾纹~
------解决方案--------------------
探讨
不加锁的情况非常简单,就是不能完成同步了。。
问题是加锁后,照2楼的解释,结果是随机的。
我试了几次,次数也不少,貌似结果全是一致的。。

------解决方案--------------------
synchronized关键字可以锁class也可以锁对象。如果它修饰的是static方法那么他锁的是class,也就是多线程访问该class加载的任何实例的synchronized方法都会有阻塞问题。如果锁的是一般方法那么java默认锁的是当前实例也就是this.那么所有使用同一个对象的线程都会产生竞争。上述例子应该属于第二种。但是你这个写法看不出问题。因为t.start()方法是吧调用线程的权利交给了jvm。jvm使用线程争抢机制确定那个线程先来执行而已。而tt.m2();方法只能说明你主线程调用m2方法。m1和m2谁先执行其实也不能保证。所有最终的结果很难说明问题。