为什么会出现线程安全问题?这和线程操作对象的工作机制有关,机制如下
1:从主存复制变量到当前工作内存
2:执行代码,改变共享变量的值
3:用工作内存数据刷新主存相关内容
如果多个线程同时执行,由于执行的时序不一样,就会导致主存的值被多个线程修改,会导致安全问题
安全问题代码
package com.cwj.test48;
public class ThreadSafety {
public static void main(String[] args) {
Count count = new Count();
for(int i=0;i<5;i++){
WorkThread workThread = new WorkThread(count);
workThread.start();
}
System.out.println("最终的值是"+count.count);
}
}
class WorkThread extends Thread {
private Count count;
public WorkThread(Count count) {
this.count = count;
}
@Override
public void run() {
super.run();
count.add();
}
}
class Count {
public int count = 0;
public void add() {
count += 1;
System.out.println("线程" + Thread.currentThread().getName() + "的count值是" + count);
}
}
运行结果
线程Thread-1的count值是2
线程Thread-3的count值是3
最终的值是2
线程Thread-0的count值是2
线程Thread-2的count值是4
线程Thread-4的count值是5
解决线程安全问题的三种方法:
1:多实例,不用单例模式
2:使用java.util.concurrent下面的类库
3:使用锁机制synchronized,lock方式
接下来使用第三种方式对代码进行改进
package com.cwj.test48;
public class ThreadSafety {
public static void main(String[] args) {
Count count = new Count();
for (int i = 0; i < 5; i++) {
WorkThread workThread = new WorkThread(count);
workThread.start();
}
try {
Thread.sleep(5l);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("最终的值是" + count.count);
}
}
class WorkThread extends Thread {
private Count count;
public WorkThread(Count count) {
this.count = count;
}
@Override
public void run() {
super.run();
count.add();
}
}
class Count {
public int count = 0;
public synchronized void add() {
count += 1;
System.out.println("线程" + Thread.currentThread().getName() + "的count值是" + count);
}
}
运行结果如下
线程Thread-0的count值是1
线程Thread-4的count值是2
线程Thread-3的count值是3
线程Thread-2的count值是4
线程Thread-1的count值是5
最终的值是5
使用隐式锁的三种方式
1:public synchronized void test(){}
2:public void test(){
synchronized(this) {
}
}
3:private byte [] lock = new byte[1];
public void test() {
synchronized(lock) {
}
}
这三种方式,第三种性能最好,第一种性能最差