线程同步问题
线程同步:多个线程操作同一资源
并发:同一个对象被多个线程同时操作
解决线程同步问题的核心,是让线程排好队一个个来(队列),同时还要使用锁确保安全。
要确保线程安全,必然会降低效率。
线程同步
方式一:使用synchronized修饰方法或代码块
每个对象都有一把锁,使用synchronized修饰方法,必须获取这个锁才能执行,没有获取到锁的线程阻塞。但如果对大的方法使用这套机制会影响效率,只读操作不需要加锁,给修改操作的代码块加锁即可。
使用synchronized默认锁的是this(类),但有时并不是这个类本身进行了增删改,所以使用锁最难的就是分析哪个对象需要进行增删改,再将这个对象加锁。
疑问点:new 了一个list,给list加synchonized代码块,如果不通过sleep延迟,打印时list数据仍然可能少。
public class UnsafeList {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
new Thread(() -> {
synchronized (list){
list.add("1");
}
}).start();
}
//try {
// Thread.sleep(1000);
//} catch (InterruptedException e) {
// e.printStackTrace();
//}
System.out.println(list.size()); //9999
}
}
解答:给list添加数据的线程还没执行完,main线程先跑了,所以打印出来会少。通过给main线程加sleep,这样可以确保数据全部添加完才打印最终结果。
public class TestThread {
public static void main(String[] args) {
new Thread(()->{
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "线程睡醒了");
}).start();
System.out.println(Thread.currentThread().getName() + "执行完毕");
}
}
main执行完毕
Thread-0线程睡醒了