2022-8-3 第七组 潘堂智 锁、多线程

1.synchronized多线程并发编程。

重量级锁。JDK1.6对synchronized进行了优化。
JDK1.6为了减少获得锁和释放锁带来的性能消耗引入的偏向锁和轻量级锁。

synchronized有三种方式来加锁,分别是:

  • 1.修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁
  • 2.静态方法,作用于当前类对象加锁,进入同步代码前要获得的当前类对象的锁
  • 3.代码块,指定加锁对象,对给定对象加锁,进入同步代码块之前要获得给定对象的锁
对于普通同步方法,锁是当前实例对象(对象锁)

对于静态同步方法,锁是当前类Class对象(类锁)

对于同步方法块,锁是Synchronized括号里配置的对象

join的作用就是,调用join的线程等一等,等我跑完,你再继续跑。
在很多情况下,主线程创建并启动子线程,如果子线程中要进行大量的耗时运算,主线程将可能早于子线程结束。如果主线程需要知道子线程的执行结果时,就需要等待子线程执行结束了。
主线程可以sleep(xx),但这样的xx时间不好确定,因为子线程的执行时间不确定,join()方法比较合适这个场景。
image

死锁

  死锁是这样一种情形:多个线程同时被阻塞,他们中的一个或者全部
  都在等待某个资源的释放,由于线程无限期的阻塞,程序就不可能正常终止。
java死锁产生四个必要条件
 * 1.互斥使用,当资源被一个线程使用(占用),别的线程不能使用。
 * 2.不可抢占,资源请求者不能强制从占有者中抢夺资源,资源只能从占有者
 *          手动释放
 * 3.请求和保持,
 * 4.循环等待,存在一个等待队列。P1占有P2的资源,P2占有了P3的资源
 *      P3占有P1的资源。形成了一个等待环路。
JDK1.6以后锁升级:
 * 1.无锁:不加锁
 * 2.偏向锁:不锁锁,只有一个线程争夺时,偏向某一个线程,这个线程不加锁
 * 3.轻量级锁:少量线程来了之后,向尝试自旋,不挂起线程。
 * 4.重量级锁:排队挂起(暂停)线程。(synchronized)

1.偏向锁

	  HotSpot的作者经过研究发现,大多数情况下,锁不仅不存在多线程竞争,而且总是由同一线程多次获得,为了让线程获得锁的代价更低而引入了偏向锁。当一个线程访问同步块并获取锁时,会在对象头和栈帧中的锁记录里存储锁偏向的线程ID,以后该线程在进入和退出同步块时不需要进行CAS操作来加锁和解锁,只需简单地测试一下对象头的Mark Word里是否存储着指向当前线程的偏向锁。如果测试成功,表示线程已经获得了锁。如果测试失败,则需要再测试一下Mark Word中偏向锁的标识是否设置成1(表示当前是偏向锁):如果没有设置,则使用CAS竞争锁;如果设置了,则尝试使用CAS将对象头的偏向锁指向当前线程。

2.轻量级锁

	  线程在执行同步块之前,JVM会先在当前线程的栈桢中创建用于存储锁记录的空间,并将对象头中的Mark Word复制到锁记录中,官方称为Displaced Mark Word。然后线程尝试使用CAS将对象头中的Mark Word替换为指向锁记录的指针。如果成功,当前线程获得锁,如果失败,表示其他线程竞争锁,当前线程便尝试使用自旋来获取锁。

3.重量级锁

	  内置锁在Java中被抽象为监视器锁(monitor)。在JDK 1.6之前,监视器锁可以认为直接对应底层操作系统中的互斥量(mutex)。这种同步方式的成本非常高,包括系统调用引起的内核态与用户态切换、线程阻塞造成的线程切换等。因此,后来称这种锁为“重量级锁”。

image

线程重入
 * 任意线程在拿到锁之后,再次获取该锁不会被该锁所阻碍
 *
 * 线程不会被自己锁死的。
 * 这就叫线程的重入,synchronized可重入锁。


	 * 1.Thread的两个静态方法:
	 *  sleep释放CPU资源,但是不会释放锁
	 *  yield方法释放CPU执行权,保留了CPU的执行资格,不常用。
	 * 2.join方法,yield出让了执行权,join就加入进来。
	 * 3.wait:释放CPU资源,释放锁
	 *  notify:唤醒等待中的线程
	 *  notifyAll:唤醒等待中的所有线程

线程的常用方法:

 * Thread类中的方法
 * 1.start:启动当前线程;执行run方法
 * 2.run:
 * 3.currentThread:静态方法,获取当前正在执行的线程
 * 4.getId():返回此线程的唯一标识
 * 5.setName(String):设置当前线程的name
 * 6.getName():获取当前线程的name
 * 7.getPriority():获取当前线程的优先级
 * 8.setPriority(int):设置当前线程的优先级
 * 9.getState():获取当前线程的声明周期
 * 10.interrupt():中断线程的执行
 * 11.interrupted():查看当前线程是否中断
posted @ 2022-08-03 20:30  阿萨德菩提子  阅读(32)  评论(0编辑  收藏  举报