《多线程编程》学习之六:String的常量池特性,锁对象的改变,volatile关键字
来源:互联网 发布:连锁店软件多少钱 编辑:程序博客网 时间:2024/04/27 17:02
1、String的常量池特性
在JVM中具有常量池缓存功能,如String s1 = "abc"; String s2 = "abd"; 这里s1与s2代表同一个String对象。当我们在同步代码块synchronized(string){ }使用String作为锁对象时,可能会出现问题。看下面例子:
例一:
测试结果:
可以看出,线程Thread-B得不到执行,这是因为String的两个值都是A,两个线程需要同一个锁对象,一旦Thread-A持有锁对象,就进入死循环,导致线程Thread-B得不到执行。这是String常量池带来的问题,大多数情况下,同步synchronized(){}代码块都不使用String作为对象锁,而改用其它,如new Object()实例化一个对象。
例二:
可见修改后的程序,线程A与B是异步执行的。
2、锁对象的改变
可见,两个线程是异步执行的,这是因为50毫秒过后,线程Thread-B获取的锁与Thread-A持有的锁不是同一个。如果把Thread.sleep(50)注释掉,则出现一下结果:
可见,虽然将锁改变了,但结果是线程之间是同步的。因为两个线程共同抢占的是同一个锁。
3、volatile关键字非原子特性
volatile关键字只能用于修饰变量,解决的是变量在多线程之间的可见性(内存模型中私有堆栈与公有堆栈,关键字volatile提醒线程每次从共享内存中读取变量,而不是从私有内存中读取),但不能保证原子性。多线程访问volatile变量不会发生阻塞。线程安全包括原子性与可见性两方面。
可见volatile关键字不保证同步性。解决办法是在addCount()方法前添加synchronized关键字。
修改如下:
运行结果:
4、使用原子类进行i++操作
可见,成功累加到10000。
但是原子类也并不完全安全。虽然incrementAndGet()方法是原子性的,但方法与方法之间的调用不是原子时,仍会出现非线程安全。例如,在一个非原子的方法中调用多个原子方法,而多线程访问这个非原子方法,则可能出现问题。
5、补充
1)volatile关键字是线程同步的轻量级实现,性能上比synchronized要好。
2)volatile能保证数据的可见性,但不能保证原子性;synchronized可以保证原子性,也可以间接保证可见性,因为它会将私有内存和公共内存中的数据做同步。
- 《多线程编程》学习之六:String的常量池特性,锁对象的改变,volatile关键字
- Java多线程String的常量池特性
- Java 多线程编程之二 volatile 关键字的使用
- Java 多线程编程之二 volatile 关键字的使用
- Java 多线程学习笔记(七)数据类型String的常量池特性
- String对象不可改变的特性
- String对象不可改变的特性
- String对象不可改变的特性
- 多线程编程核心技术读书笔记(二):对象及变量的并发访问(volatile关键字)
- 多线程共享对象之volatile关键字
- C语言如何改变一个常量的值和volatile关键字
- 数据类型String常量池的特性
- Java多线程的volatile关键字
- Volatile关键字的学习
- Volatile(与多线程编程等方面有关的一个关键字)
- 多线程之volatile关键字
- 多线程之volatile关键字
- 多线程之volatile关键字
- json的java类库:Json-lib、Gson
- 第8周OJ项目1 求倒数和
- IE兼容性优化
- IOError: No translation files found for default language zh-cn.
- Eratosthenes筛法求素数
- 《多线程编程》学习之六:String的常量池特性,锁对象的改变,volatile关键字
- *((volatile unsigned int*)0xFFE00000)这种格式的理解
- 【bzoj2463】 [中山市选2009]谁能赢呢?
- Java Filter
- jquery 和其他js框架同时使用的不兼容问题解决方法
- 打开相册/相机 并裁剪
- 面向对象思维
- 面向对象_内部类分类及成员内部类的直接使用
- 在C#中创建accss数据库和表