一提到多线程编程就会想到与之相对的线程安全问题,这是一个在多线程下必须解决的问题。下面是自己
在学习多线程中关于线程安全方面的一些总结,如有错误、遗漏的地方,欢迎指正,大家一起进步。
1.什么是线程安全
当多个线程并发访问修改一个变量或者类时,在不需要做额外的同步的情况下,总能得到预期的结果!
2.线程安全的核心问题
1.原子性
所谓原子性是指一个单独的,不能在分割的操作。通俗点:即对一个或者一组变量的 读-写-改 操作
不可被打断,分割。
2.内存可见性
即当一个线程对一个共享变量修改后,其他访问这个变量的线程能获取到修改后的最新值。
3.实现线程安全的方法
1.synchronized 、 Lock
这是一种很常见,也很粗暴的解决方式。你不是并发访问嘛 ,我给你锁上,让你串行不就可以了。
这种方式优点是:简单!简直不要太简单,就是一个新手都会。
缺点是:降低了程序的并发性,效率。
2.使用线程安全类
所谓线程安全类,就是指在多线程下不需要进行额外同步或者少量同步就能保证线程安全的类。
比如String, ConcurrentHashMap。这些类在内部实现上已经封装了所有必要的同步。
总的来说线程安全类分为如下几种:
1.绝对线程安全类:
(1).没有属性(状态)的类。
(2).不可变类。即所有的属性都是final的 (如String类就是不可变类)。
2.线程安全类:
(1).高效不可变类
进行一些操作时需要进行额外的同步,如ConcurrentHashMap 在对其进行迭代时需要额外的锁。
这种方式的优点是:在保证线程安全的情况下,同时能保证线程的并发性。
缺点是:实现相对于加锁更为复杂,一但设计不好就会出现问题。需要有比较丰富的
多线程编程经验。
3.栈限制(线程封闭)
栈限制是实现线程安全最简单的方式之一。
所谓栈限制,简单直白一点就是不共享数据,将对象限制在栈内部,这种情况下就跟单线程一样了,数据已经成为
线程私有的了,就算被限制的对象不是线程安全的,也不会引发线程安全问题。
这种方式的优点是:完全没有加锁方面的性能开销,性能与单线程一样,如果有性能问题,那都是代码写的有问题。
缺点是:貌似没有什么缺点,只要能用这种方式解决,那肯定是首选!
4. volatile
volatile是一种轻量级的同步,只能保证内存可见性,不能保证操作的原子性。所以其使用是有局限性的,通常是
在其值的修改不受已有值的影响下才使用,如 当作开关
public class MyThread implements Runnable {
private volatile boolean stop = false;
@override
public void run() {
int i = 0;
while (!stop) {
i++;
}
}
public void stop() {
stop = true;
}
}