博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[置顶] 深入探析Java线程锁机制
阅读量:5871 次
发布时间:2019-06-19

本文共 1910 字,大约阅读时间需要 6 分钟。

今天在iteye上提了一个关于++操作和线程安全的问题,一位朋友的回答一言点醒梦中人,至此我对Java线程锁有了更加深刻的认识。在这里也做个总结供大家参考。

      先看几段代码吧!

   代码一:

[java]
  1. public class TestMultiThread2 implements Runnable{  
  2.   
  3.     private static Object o = new Object();  
  4.       
  5.     private static Integer si = 0;  
  6.       
  7.     private static AtomicInteger flag = new AtomicInteger();  
  8.       
  9.     @Override  
  10.     public void run() {  
  11.         for(int k=0;k<2000000;k++){  
  12.             synchronized(si){  
  13.                 si++;  
  14.             }  
  15.         }  
  16.         flag.incrementAndGet();  
  17.     }  
  18.     public static void main(String[] args) throws InterruptedException{  
  19.         TestMultiThread2 t1 = new TestMultiThread2();  
  20.         TestMultiThread2 t2 = new TestMultiThread2();  
  21.         ExecutorService exec1 = Executors.newCachedThreadPool();  
  22.         ExecutorService exec2 = Executors.newCachedThreadPool();  
  23.         exec1.execute(t1);  
  24.         exec2.execute(t2);  
  25.         while(true){  
  26.             if(flag.intValue()==2){  
  27.                 System.out.println("si>>>>>"+si);      
  28.                 break;  
  29.             }  
  30.             Thread.sleep(50);  
  31.         }  
  32.   
  33.           
  34.     }     
  35.       
  36. }  

   为了方便看,重复的就不插入了,从代码二到代码四只插入run()方法中的代码,其他地方都一样

  代码二:

[java]
  1. public void run() {    
  2.     for(int k=0;k<2000000;k++){    
  3.         synchronized(o){    
  4.             si++;    
  5.         }    
  6.     }    
  7.     flag.incrementAndGet();    
  8. }    

  代码三:

[java]
  1. public void run() {    
  2.     for(int k=0;k<2000000;k++){    
  3.         synchronized(o){    
  4.             si++;    
  5.             o = new Object();    
  6.         }    
  7.     }    
  8.     flag.incrementAndGet();    
  9. }    

    代码四: 

[java]
  1. public void run() {    
  2.      for(int k=0;k<2000000;k++){    
  3.          synchronized(o){    
  4.              si++;    
  5.              Object temp = o;    
  6.              o = new Object();    
  7.              o = temp;    
  8.          }    
  9.      }    
  10.      flag.incrementAndGet();    
  11.  }    

  有了这四段代码我想问题大概可以说明白了,这里说一下输出吧。

 

  代码一:<4000000

  代码二:=4000000

  代码三:<4000000

  代码四:<4000000(PS:这个结果非常接近4000000)

 

      这里说明一下我测试中碰到的问题,代码四一直没有跑出我想要的结果,主要是开始我设的循环次数太少,其实这里如果要这个现象更加明显一些可以在中间多new 几个Object 如下面的代码五,这样现象就比较明显了.

  代码五:

[java]
  1. public void run() {    
  2.     for(int k=0;k<2000000;k++){    
  3.         synchronized(o){    
  4.             si++;    
  5.             Object temp = o;    
  6.             for(int m=0;m<10;m++){    
  7.                 o = new Object();    
  8.             }    
  9.             o = temp;    
  10.         }    
  11.     }    
  12.     flag.incrementAndGet();    
  13. }    

 为什么会出现上面的现象:

     代码一:当si做++操作后(可以直接看字节码,这里不贴了),在putstatic之前有几步操作,就是我们常说的非原子操作,而这时候si已经不是原来的对象了,这样锁对另外一个线程来说就失效了,我想代码三和代码四就是最好的佐证,代码四更有说服力。当时因为没有出现预想的情况困惑了挺久。

    其实这里用字节码来解释还不是很严谨,最好的当然直接是汇编代码

    如有什么问题还希望各位读者指正。

zhuanzi:http://blog.csdn.net/luohuacanyue/article/details/8307617

你可能感兴趣的文章
使用大于16TB的ext4文件系统
查看>>
c/c++标准库中的文件操作总结
查看>>
day20 Python 高阶函数,函数,嵌套,闭包 装饰器
查看>>
记录时间的方法
查看>>
667. Beautiful Arrangement II
查看>>
Intellij idea 快捷键 生成序列化ID
查看>>
[原创]错误提示:disagrees about version of symbol module_layout,解决方法
查看>>
费马小定理&欧拉定理
查看>>
oracle数组的使用
查看>>
POJ3342 Party at Hali-Bula(树型DP求最大独立集+唯一解判断)
查看>>
matplotlib ----- 多子图, subplots
查看>>
无线路由器连接电信光纤宽带光猫设置方法(转)
查看>>
git的CentOS服务端安装和windows客户端的使用
查看>>
会议06
查看>>
快速提高看盘能力的十大方法
查看>>
线性代数与矩阵论 习题 1.2.1
查看>>
度量空间的一个例子:离散度量空间
查看>>
从有理数到实数(序)
查看>>
自适应滤波:最小二乘法
查看>>
linux下部署jdk+Tomcat
查看>>