java并发编程线程安全问题
程序员文章站
2022-04-23 14:17:01
...
1.线程安全:管理对共享的可变状态的访问。状态----指的是静态变量或实例变量。
2.共享:静态变量----类的使用者共享,实例变量----对象使用者共享。--目的:线程间相互交流
3.可变:对变量有写的过程,只读当然就是不可变的。
4.原子操作:意为"不可被中断的一个或一系列操作"
5.解决线程安全的思路:(对应一场安全的考试的情景)
(1)共享变量只读;----不可变性
情景示例:放英语听力
代码示例:单例(饿汉式)
package chapter1.singelton01; public class MyObject { //共享的静态变量,只有这里初始化,其他任何地方都不能写入 private static MyObject myObject = new MyObject(); private MyObject() { } public static MyObject getInstance(){ return myObject; } } public class MyThread extends Thread { @Override public void run() { System.out.println(MyObject.getInstance().hashCode()); } } public class Run { public static void main(String[] args) { MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); MyThread t3 = new MyThread(); t1.start(); t2.start(); t3.start(); } } 三个线程访问的结果相同
使用场景示例:dao层写的sql语句---private static final String SQL_INSERT = ""
用spring容器管理的单例bean,多数情况我们保证bean对象的不可变性
(2)可变变量不共享:----线程封闭
情景示例:每个考生一份试卷
代码示例:
package chapter1.t0020; public class MyThread extends Thread { private int count = 5; public MyThread(String name) { super(); this.setName(name); } @Override public void run() { super.run(); while(count>0){ count--; System.out.println("由"+MyThread.currentThread().getName()+"计算,count="+count); } } } public class Run { public static void main(String[] args) { MyThread myThread1 = new MyThread("A"); MyThread myThread2 = new MyThread("B"); MyThread myThread3 = new MyThread("C"); myThread1.start(); myThread2.start(); myThread3.start(); } } myThread1 、myThread2、 myThread3每个对象都有自己的 count 变量
使用场景示例:struts2的action的原型模式,每个线程有自己的action对象
ThreadLocal变量的设计
(3)共享可变的变量原子操作:----加锁
情景示例:阅卷老师改完一题,交给下一位老师改下一题
代码示例:单例(懒汉式)
public class MyObject { private static MyObject myObject; private MyObject() { } public synchronized static MyObject getInstance(){ if(myObject!=null){ }else{ myObject = new MyObject(); } return myObject; } } public class MyThread extends Thread { @Override public void run() { System.out.println(MyObject.getInstance().hashCode()); } } public class Run { public static void main(String[] args) { MyThread t1 = new MyThread(); MyThread t2 = new MyThread(); MyThread t3 = new MyThread(); t1.start(); t2.start(); t3.start(); } }
使用场景示例:spring对bean的初始化,ConcurrentMap实现
锁带来的问题,以及解决这些问题锁产生的新的方案----很多技术都是对另一种技术的补充,没有替代关系,只有在特定的时间,特定的场合更适合。你的工作是找到更适合的方案,并使用它。