20220803 第一组 于芮 多线程基础(第二十三天)
锁
1.synchronize多线程并发编程
JDK1.6时进行优化,为了减少获得锁和释放锁带来的性能的消耗引入的偏向锁和轻量级锁
synchronize三种加锁方式
1.修饰实例方法,当前实例加锁,进入同步代码之前或的当前实例对象的锁
2.静态方法,作用当前类对象加锁,进入同步代码之前获得当前 类对象的锁
3.代码块 指定加锁对象,对指定对象加锁,进入同步代码块之前获得指定对象的锁
对应锁对象
1.实例方法:调用该方法的实例
2.静态方法:类对象(.class形式)
3.this:调用该方法的实例对象
4.类对象
操作共享数据的代码
共享数据:多个线程共同操作的变量,都可以充当锁
关于同步方法
1.同步方法依然涉及到同步锁对象,不需要我们写
2.非静态同步方法,同步锁就是this
3.静态的同步方法,同步监控器就是类本身
同步代码块
1.选好同步监视器(锁),推荐使用类对象,第三方对象,this
2.在实现接口创建的线程类中,同步代码块不可以用this来充当同步锁
同步的方式,解决线程的安全的问题
操作同步代码块时,只有一个线程能够参与,其他线程等待,相当于一个单线程的过程,效率低
synchronize只针对于当前JVM可以解决线程安全问题,不可以跨JVM解决问题。
死锁
多个线程同时被阻塞,他们中的一个或者全部都在等待某个资源的释放,由于线程的无限期阻塞,程序就不可能正常终止
死锁产生的四个必要条件
1.互斥使用:当资源背个线程使用,别的线程不能使用
2.不可抢占:资源请求者不能强制从占有者中抢夺资源,资源智能从占有者手动释放
3.请求和保持
4.循环等待:存在一个等待队列,形成一个等待的环路
线程重入(synchronize可重入)
任意线程拿到锁之后,再次获得该锁不会被该锁阻碍,线程不会被自己锁死
JDK1.6后锁升级
1.无锁,不加锁
2.偏向锁,不锁锁,只有一个线程争夺时,偏向某一个线程,这个线程不加锁
3.轻量级锁 少量线程来了以后,向尝试自旋,不挂起线程
4.重量级锁 排队挂起(暂停)线程
挂起线程和恢复线程需要转入内核状态中完成这些操作,给系统的并发性带来很大的压力
在许多应用上共享数据的锁定状态,只会持续很短的时间,为了这段时间会挂起和恢复并不值得,
我们可以让后面的想线程等待一下,不要放弃处理器的执行时间,就为了让线程等待,我们只需要让线程执行一个循环、自旋【自旋锁】
thread的两个静态方法
sleep释放CPU资源,但是不会释放锁
yield方法释放CPU执行权,保留了CPU的执行资格
join方法:yield让出了执行权,join就加入进来
notify():唤醒正在等待的下一个线程
notifyall():唤醒正在等待的所有线程
wait(long timeout):当前线程进入等待状态
wait():释放CPU资源,释放锁
线程的通信
sleep和wait的区别
1.出处
2.锁的控制
线程的退出
使用退出标志,线程正常退出,run方法结束后终止程序
不要使用stop()方法
interrupt方法:中断线程
调用interrupt方法会抛出interruptedexception异常,捕获后再做停止线程的逻辑
如果线程while(TRUE)运行的状态,interrupt方法无法中断线程
线程的常用方法
start()启动方法
run()
current thread静态方法:获取当前正在执行的数据
getid:返回此线程的唯一表示
setname:设置当前线程的name
getname:获取当前线程的name
getpriority:获取当前线程优先级
setpriority:设置当前线程的优先级
getstate:获取当前线程的生命周期
interrupt:终止当前线程
interrupted:查看当前进程是否被中断
isdaemon:查看是否是守护线程
这就是今天的学习内容了,还有许多实例,今天的实例是生产者和消费者的实例,一起来看看吧!
1 package C0803; 2 3 public class Car { 4 private String name; 5 private Integer id; 6 private boolean flag=false; 7 8 public Car() { 9 } 10 11 public Car(String name, Integer id) { 12 this.name = name; 13 this.id = id; 14 } 15 public synchronized void get(){ 16 if(!flag){ 17 try { 18 super.wait(); 19 }catch (InterruptedException e){ 20 e.printStackTrace(); 21 } 22 } 23 System.out.println("购买了汽车"+this.name+"->"+this.id); 24 flag=false; 25 super.notify(); 26 } 27 public synchronized void set(String name,Integer id){ 28 if(flag){ 29 try { 30 super.wait(); 31 }catch (InterruptedException e){ 32 e.printStackTrace(); 33 } 34 } 35 this.name=name; 36 try { 37 Thread.sleep(10); 38 }catch (InterruptedException e){ 39 e.printStackTrace(); 40 } 41 this.id=id; 42 System.out.println("生产了汽车:"+name+"->"+id); 43 flag=true; 44 super.notify(); 45 } 46 }
1 package C0803; 2 3 public class CarConsumer implements Runnable { 4 private Car car; 5 6 public CarConsumer() { 7 } 8 9 public CarConsumer(Car car) { 10 this.car = car; 11 } 12 @Override 13 public synchronized void run(){ 14 for (int i = 1; i <=100 ; i++) { 15 try { 16 Thread.sleep(20); 17 }catch (InterruptedException e){ 18 e.printStackTrace(); 19 } 20 car.get(); 21 } 22 } 23 }
1 package C0803; 2 3 public class CarProduction implements Runnable{ 4 private Car car; 5 6 public CarProduction() { 7 } 8 9 public CarProduction(Car car) { 10 this.car = car; 11 } 12 13 @Override 14 public synchronized void run() { 15 for (int i = 1; i <=100 ; i++) { 16 try { 17 Thread.sleep(20); 18 }catch (InterruptedException e){ 19 e.printStackTrace(); 20 } 21 if(i%2==0){ 22 car.set("汽车"+i,i); 23 }else { 24 car.set("卡车"+i,i); 25 } 26 } 27 } 28 29 30 }
package C0803; public class Demo { public static void main(String[] args) { Car car=new Car(); CarProduction carProduction=new CarProduction(car); CarConsumer carConsumer=new CarConsumer(car); new Thread(carConsumer).start(); new Thread(carProduction).start(); } }