一:线程不安全的例子1和解决:类中的int变量
不安全的情况:
public class ThreadUnsafeExampleInt {
//存储变量的类
static class VariableClass {
public int num = 0;
public int getNum() {
return num;
}
public void incrementAdd() {
this.num++;
}
}
//线程类
static class MyThread extends Thread {
private VariableClass variableClass;
public MyThread(VariableClass variableClass) {
this.variableClass = variableClass;
}
public void run() {
variableClass.incrementAdd();
System.out.println(variableClass.getNum());
}
}
public static void main(String[] args) {
VariableClass variable = new VariableClass();
for (int i = 0; i < 2000; i++) {
new MyThread(variable).start();
}
//1994
//1995
//1996
//1997
//1998
//1999 最后漏了1(某个时刻,两个线程通过获取到的num是相同的,然后两个线程都++后,效果是只++了一次)
}
}
解决: 加锁 synchronized
public class ThreadSafeExampleInt {
//存储变量的类
static class VariableClass {
public int num = 0;
public int getNum() {
return num;
}
public void incrementAdd() {
this.num++;
}
}
//线程类
static class MyThread extends Thread {
private VariableClass variableClass;
public MyThread(VariableClass variableClass) {
this.variableClass = variableClass;
}
public void run() {
synchronized (variableClass){
variableClass.incrementAdd();
System.out.println(variableClass.getNum());
}
}
}
public static void main(String[] args) {
VariableClass variable = new VariableClass();
for (int i = 0; i < 2000; i++) {
new MyThread(variable).start();
}
//1997
//1998
//1999
//2000 加锁之后,数量正确
}
}
二:线程不安全的例子2和解决:操作同一个List
不安全的情况:
public class ThreadUnsafeExampleList {
public static void main(String[] args) throws InterruptedException {
List<String> list = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
new Thread(()->{
list.add(Thread.currentThread().getName());
}).start();
}
Thread.sleep(4000);
System.out.println(list.size()); // 999 少了1个
}
}
解决:
public class ThreadSafeExampleList {
public static void main(String[] args) throws InterruptedException {
List<String> list = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
new Thread(()->{
synchronized (list){
list.add(Thread.currentThread().getName());
}
}).start();
}
Thread.sleep(4000);
System.out.println(list.size()); // 1000 正确
}
}