今天学习synchronized关键字时,在百度上看到一个很有意思的问题,经过一番学习,对synchronized有了比较深入的理解
百度知道提问如下----------------------------
public class Training{
public static void main(String ars[])throws IOException
{
Test t = new Test();
Thread t1 = new Thread(t);
Thread t2 = new Thread(t);
t1.start();
t2.start();
}
}
class Test implements Runnable{
static Integer count = 0;
public int flag = 1;
public void run(){
if (flag==0)
m2();
else
m1();
}
public synchronized void m1(){
// count = 1;
flag = 0;
for(int i = 0;i < 50; i++){
count++;
System.out.println("m1's printing : count = "+count);
}
}
public void m2(){
// count = 0;
synchronized(count){
count = 2;
for(int i = 0;i < 50; i++)
System.out.println("m2's printing : count = "+count);
}
count = 3;
}
}
本来觉得应该m1先输出结束m2再开始输出或者m1输出几m2输出完m1继续结却两者轮流输出(由于输出结太长里贴出来了)原因呢我已经m2里把count锁了
当synchronized修饰函数时候该函数无法被其进程调用;修饰对象时候大括号内代码执行完前其线程无法修改改对象我理解错了
m2里面把count对象锁了还能被m1修改呢
---------------------------------------由于知道里的答案都不正确,特将学习到的内容记录一下
上诉代码中两点错误:
1:你如果将count作为锁,就不要改变count的值。当你使用count作为锁的时候,你不开锁,别人的确进不了门,但是锁上门以后第一件事却直接count++就相当于你自己把锁给砸了,当然起不了锁的作用。
2:synchronized修饰函数时,表明函数执行完之前不能被另一个函数调用,这个函数里你只执行一次M1,所以synchronized关键字没有起到任何意义
修改方法也十分简单,1:去除修改count值的操作。然后m1使用count对循环输出加锁。2。另外一定一个锁对象,实现加锁操作。
总结:为什么JAVA不能对变量加锁?因为要对一个对象加锁,需要一个锁指向这个对象,锁有计数器,对这个对象进行监控。。。。。基本类型是不可能被指针指着的。。。。。
JAVA为什么不推荐对封装变量的对象加锁?因为这个对象所指值可能被非预期的改变,给程序带来不可预见的安全漏洞。