JUC并发编程(二)-- 线程八锁
线程八锁,指的就是线程中关于锁的八个问题,用来分辨清晰Java多线程中,锁究竟锁的是什么。
以下 5 和 6 两个问题分别是两个子问题的综合,一共八个问题。
注:下面的所有问题中,A和B两个线程,分别按顺序在main() 中创建。也就是A先拿到锁。
1、两个线程,分别调用同一个资源类的两个方法,哪个先执行?
2、两个线程A和B,分别调用同一个资源类的两个方法,A线程休眠3秒,哪个线程先执行?
回答:谁先拿到锁谁先执行。
原因:锁是锁的方法的调用者。
代码实例:
资源类:
package com.zhan.juc.lockBy8question;
import java.util.concurrent.TimeUnit;
/**
* @Author Zhanzhan
* @Date 2020/11/28 15:43
* 资源类
*/
public class Data {
public synchronized void printA(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("执行线程A");
}
public synchronized void printB(){
System.out.println("执行线程B");
}
}
线程操作类:
package com.zhan.juc.lockBy8question;
import java.util.concurrent.TimeUnit;
/**
* @Author Zhanzhan
* @Date 2020/11/28 15:42
* 锁的八个问题--第一个
* 两个线程,分别调用同一个资源类的两个方法,哪个先执行?
*/
public class Question1 {
public static void main(String[]args) throws InterruptedException {
Data data = new Data();
//
new Thread(()->{
data.printA();
}, "A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
data.printB();
},"B").start();
}
}
运行结果如下:
3、非同步方法是否会受到对象锁的影响?
问题详述:两个线程A和B,分别调用同一个资源类里的方法,其中A线程调用的是同步方法,B线程调用的是普通方法,其中A线程调用的同步方法休眠3秒,问,哪个线程先执行?
回答:B线程先执行。
原因:非同步方法不会受到对象锁的影响。
代码实例:
资源类:
package com.zhan.juc.lockBy8question;
import java.util.concurrent.TimeUnit;
/**
* @Author Zhanzhan
* @Date 2020/11/28 15:43
* 资源类
*/
public class Data {
public synchronized void printA(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("执行线程A");
}
public synchronized void printB(){
System.out.println("执行线程B");
}
public void hello(){
System.out.println("hello");
}
}
线程操作类:
package com.zhan.juc.lockBy8question;
import java.util.concurrent.TimeUnit;
/**
* @Author Zhanzhan
* @Date 2020/11/28 20:35
* 锁的八个问题--第三个
* 非同步方法是否会受到对象锁的影响
*/
public class Question3 {
public static void main(String[]args) throws InterruptedException {
Data data = new Data();
// 这里的线程A调用的是data对象的同步方法
new Thread(()->{
data.printA();
}, "A").start();
TimeUnit.SECONDS.sleep(1);
// 这里的线程B调用的是data对象的非同步方法
new Thread(()->{
data.hello();
},"B").start();
}
}
运行结果如下:
4、同一个类中两个对象的同步方法时候会相互影响?
问题描述:线程A调用 Data 类的 对象data1的同步方法a(),其中a() 中会休眠3秒,线程B调用 Data 类的 对象 data2 的同步方法b(),谁先执行?
回答:线程B先执行。
原因:同一个类的两个对象的同步方法不会互相影响。
代码实例:
资源类:
package com.zhan.juc.lockBy8question;
import java.util.concurrent.TimeUnit;
/**
* @Author Zhanzhan
* @Date 2020/11/28 15:43
* 资源类
*/
public class Data {
public synchronized void printA(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("执行线程A");
}
public synchronized void printB(){
System.out.println("执行线程B");
}
public void hello(){
System.out.println("hello");
}
}
线程操作类:
package com.zhan.juc.lockBy8question;
import java.util.concurrent.TimeUnit;
/**
* @Author Zhanzhan
* @Date 2020/11/28 20:40
* 锁的八个问题--第四个
* 两个线程 A 和 B ,分别调用同一个资源类的 两个 对象的同步方法, 是否会互相影响
*/
public class Question4 {
public static void main(String[] args) throws InterruptedException {
Data data1 = new Data();
Data data2 = new Data();
new Thread(() -> {
data1.printA();
}, "A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(() -> {
data2.printB();
}, "B").start();
}
}
运行结果如下:
5、同一个类中的两个静态同步方法时候会互相影响?
问题描述:同一个资源类中,设置两个静态的同步方法a() 和 b(),然后用线程A调用a(),线程B调用b(),其中a() 中休眠3秒,问,哪个线程先执行?
回答:线程A先执行。
原因:静态同步方法,锁的是整个class,所以这两个静态的同步方法会互相影响。
代码实例:
package com.zhan.juc.lockBy8question;
import java.util.concurrent.TimeUnit;
/**
* @Author Zhanzhan
* @Date 2020/11/28 20:54
* 锁的八个问题--第四个
* 同一个资源类中,设置两个静态的同步方法a() 和 b(),然后用线程A调用a(),线程B调用b(),其中a() 中休眠3秒,问,哪个线程先执行
*/
public class Question5 {
public static void main(String[]args) throws InterruptedException {
new Thread(()->{
Data5.printA();
},"A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
Data5.printB();
},"B").start();
}
}
/**
* 资源类,里面有两个静态同步方法
*/
class Data5{
public static synchronized void printA(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("执行线程A");
}
public static synchronized void printB(){
System.out.println("执行线程B");
}
}
运行结果如下:
6、同一个类中,一个静态同步方法和一个普通同步方法,会相互影响吗?
问题描述:同一个资源类中,有一个静态同步方法 a(),和一个普通同步方法 b(),然后用线程A调用a(),线程B调用b(),其中a() 中休眠3秒,问,哪个线程先执行?
回答:线程B先执行。
原因:静态同步方法的锁,锁的是当前的Class对象;普通同步方法的锁,锁的是当前new 出来的对象。两个锁不是锁的同一个东西。
代码实例:
package com.zhan.juc.lockBy8question;
import java.util.concurrent.TimeUnit;
/**
* @Author Zhanzhan
* @Date 2020/11/28 22:09
* 线程八锁
* 同一个资源类中,有一个静态同步方法 a(),和一个普通同步方法 b(),然后用线程A调用a(),线程B调用b(),其中a() 中休眠3秒,哪个线程先执行?
*/
public class Question6 {
public static void main(String[] args) throws InterruptedException {
Data6 data = new Data6();
new Thread(Data6::printA, "A").start();
TimeUnit.SECONDS.sleep(1);
new Thread(()->{
data.printB();
}, "B").start();
}
}
class Data6{
/**
* 这里锁的是当前的Class对象
*/
public static synchronized void printA(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("执行线程A");
}
/**
* 这里锁的是当前的调用者对象,即 new 出来的对象
*/
public synchronized void printB(){
System.out.println("执行线程B");
}
}
运行结果如下: