- A+
一,线程的同步
原因: Java允许多线程并发执行,当多个线程同时操作一个可共享资源时,将会导致相互之间产生冲突,因此加入同步锁来避免该线程没有完成操作之前,被其他线程的调用,从而保证该资源的唯一性和准确性。
三种实现同步方式:
-
同步代码块
-
同步方法
-
锁机制 Lock
格式:
synchronized(任意对象){
操作共享数据的代码
}
注意:
默认情况锁是打开的,只要有一个线程进去执行代码,锁就会关闭
当线程执行完出来了,锁才会自动打开
锁对象可以是任意对象,但是多个线程必须使用同一把锁
好处:解决了多线程的数据安全问题
弊端:当线程很多时,因为每个线程都会去判断同步上的锁,很消耗资源,降低程序运行效率
什么叫代码的同步
使用同步锁以避免在该线程没有完成操作之前,被其他线程的调用,从而保证该变量的唯一性和准确性
二,同步方法
格式:
修饰符 synchronized 返回值类型 方法名(方法参数){
}
区别:
-
同步代码块可以锁住指定代码,同步方法是锁住方法中所有代码
-
同步代码块可以指定锁住对象,同步方法不能
注意:
同步方法是有默认存在的锁对象
对于非static方法,同步锁就是this
对于static方法,我们使用当前方法所在类的字节码对象
三,Lock锁
JDK5后提供了一个新的锁对象
提供了获得锁和释放锁的方法:
void lick() 获得锁
void unlock() 释放锁
Lock锁是接口不能直接实例化,采用实现类ReentrantLock来实例化
Lock lock = new ReentLock();
死锁:
两个线程对两个同步锁对象具有循环依赖,就大概会出现死锁
比如:
将大象放进冰箱!
大象锁:冰箱你把门打开,我才过去!
冰箱锁:你走过来,我才打开门!
避免:不适用锁的嵌套
生产者消费者
比如:顾客和厨师
线程池的使用:
public class Demo2 {
public static void main(String[] args) {
//新建了一个线程任务
Demo2Runnable demo2Runnable = new Demo2Runnable();
ExecutorService executorService = Executors.newFixedThreadPool(5);
//submit:将线程任务提交到线程池中 执行线程
executorService.submit(demo2Runnable);
executorService.submit(demo2Runnable);
executorService.submit(demo2Runnable);
executorService.submit(demo2Runnable);
executorService.submit(demo2Runnable);
//关闭线程池
executorService.shutdown();
}
}