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

先看几段代码吧!

代码一:

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

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

代码二:

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

代码三:

  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. }

代码四:

  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 如下面的代码五,这样现象就比较明显了.

代码五:

  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

[置顶] 深入探析Java线程锁机制的更多相关文章

  1. Java 线程锁机制 -Synchronized Lock 互斥锁 读写锁

    (1)synchronized 是互斥锁: (2)ReentrantLock 顾名思义 :可重入锁 (3)ReadWriteLock :读写锁 读写锁特点: a)多个读者可以同时进行读b)写者必须互斥 ...

  2. JAVA线程锁-读写锁

    JAVA线程锁,除Lock的传统锁,又有两种特殊锁,叫读写锁ReadWriteLock 其中多个读锁不互斥,读锁和写锁互斥,写锁和写锁互斥 例子: /** * java线程锁分为读写锁 ReadWri ...

  3. Java线程锁一个简单Lock

    /** * @author * * Lock 是java.util.concurrent.locks下提供的java线程锁,作用跟synchronized类似, * 单是比它更加面向对象,两个线程执行 ...

  4. Java线程锁&分布式锁的理解及应用

    了解Java线程锁之前,先理解线程和进程的定义.进程是操作系统分配资源(CPU)的基本单位,线程是CPU执行的基本单位,一个进程可拥有多个线程,同进程间的多个线程共享分配给进程的资源.比如启动JVM时 ...

  5. 工作常用4种Java线程锁的特点,性能比较、使用场景

    多线程的缘由 在出现了进程之后,操作系统的性能得到了大大的提升.虽然进程的出现解决了操作系统的并发问题,但是人们仍然不满足,人们逐渐对实时性有了要求. 使用多线程的理由之一是和进程相比,它是一种非常花 ...

  6. Java的锁机制--synchronsized关键字

    引言 高并发环境下,多线程可能需要同时访问一个资源,并交替执行非原子性的操作,很容易出现最终结果与期望值相违背的情况,或者直接引发程序错误. 举个简单示例,存在一个初始静态变量count=0,两个线程 ...

  7. Java线程锁,synchronized、wait、notify详解

    (原) JAVA多线程这一块有点绕,特别是对于锁,对锁机制理解不清的话,程序出现了问题也很难找到原因,在此记录一下线程的执行以及各种锁. 1.JAVA中,每个对象有且只有一把锁(lock),也叫监视器 ...

  8. lesson3:java的锁机制原理和分析

    jdk1.5之前,我们对代码加锁(实际是对象加锁),都是采用Synchronized关键字来处理,jdk1.5及以后的版本中,并发编程大师Doug Lea在concurrrent包中提供了Lock机制 ...

  9. java的锁机制

    一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在Java里边就是拿到某个同步对象的锁(一个对象只有一把锁): 如果这个时候同步对象的锁被其他线程拿走了,他(这个线 ...

随机推荐

  1. Check which .NET Framework version is installed

    his article will help you to know which .NET Framework version is installed from command line. Check ...

  2. 自然语言交流系统 phxnet团队 创新实训 项目博客 (七)

    在本项目中使用到的“语音转文本”的技术总结: 语音转文本部分是调用的科大讯飞的在线语音,它的激发方式是按键,通过按钮触发开启安卓设备的录音,此部分需要在源码中写入关于安卓权限的要求,来调用安卓的录音权 ...

  3. 编写一个函数,计算字符串中含有的不同字符的个数。字符在ACSII码范围内(0~127)。不在范围内的不作统计。

    题目描述 编写一个函数,计算字符串中含有的不同字符的个数.字符在ACSII码范围内(0~127).不在范围内的不作统计. 输入描述: 输入N个字符,字符在ACSII码范围内. 输出描述: 输出范围在( ...

  4. python3两个字典的合并

    两个字典的合并其实很简单,直接用dict的update即可,代码如下: # /usr/bin/python3 # -*- encoding: utf-8 -*- ", "" ...

  5. tpshop全局公共方法

    TPshop 全局公告函数库 前后台可用  这里只列出有哪些方法, 简单描述, 具体的函数体查看 Application\Common\Common\function.php 文件 <?php ...

  6. 在Ubuntu14.04上编译Android4.0.1出现的几个问题

    一. 工具 sudo apt-get install git-core gnupg flex bison gperf build-essential \       zip curl libc6-de ...

  7. poj 1700 Crossing River C++/Java

    http://poj.org/problem?id=1700 题目大意: 有n个人要过坐船过河,每一个人划船有个时间a[i],每次最多两个人坐一条船过河.且过河时间为两个人中速度慢的,求n个人过河的最 ...

  8. cuffquant 定量的结果全部为-nan

    cuffquant 定量的过程中,当所有基因或者转录本的表达量都为0时,定量的结果就回全部是-nan  , 而不是0: 出现这种情况有两种原因: 1) 参考基因组搞错了,比对和定量的不是同一个参考基因 ...

  9. php判断文件存在是用file_exists 还是 is_file

    From: http://www.php100.com/html/php/hanshu/2013/0905/4672.html [导读] 在写程序时发现在判断文件是否存在时,有两种写法,有的人用了is ...

  10. 【Ubuntu】录屏软件

    http://www.leesven.com/2378.html sudo apt-get install kazam