8锁问题:关于锁的8个问题
public class demo01 {
public static void main(String[] args) {
Phone1 phone = new Phone1();
new Thread(()->{
phone.send();
},"A").start();
// 延时2秒
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.call();
},"B").start();
}
}
class Phone1{
public synchronized void send(){
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
}
① 标准情况下,上面两个线程先打印发短信还是打电话?
结果:
发短信
打电话
public class demo02 {
public static void main(String[] args) {
Phone2 phone = new Phone2();
new Thread(()->{
phone.send();
},"A").start();
// 延时2秒
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.call();
},"B").start();
}
}
class Phone2{
public synchronized void send(){
// 延时4秒
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
}
② send方法延时4秒,上面两个线程先打印发短信还是打电话?
结果:
发短信
打电话
synchronized 锁的对象是方法的调用者
两个线程用的同一个锁,谁先拿到锁谁先执行,另一个堵塞
synchronized是重度锁,当一个线程得到锁,其他线程则死等
public class demo03 {
public static void main(String[] args) {
Phone3 phone = new Phone3();
new Thread(()->{
phone.send();
},"A").start();
// 延时2秒
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.hello();
},"B").start();
}
}
class Phone3{
public synchronized void send(){
// 延时4秒
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
public void hello(){
System.out.println("hello");
}
}
③ 加了一个普通方法后,上面两个线程先输出发短信还是hello?
结果:
hello
发短信
hello() 方法是普通方法,没有synchronized,不是同步方法,不受锁的影响先输出
public class demo04 {
public static void main(String[] args) {
Phone4 phone1 = new Phone4();
Phone4 phone2 = new Phone4();
new Thread(()->{
phone1.send();
},"A").start();
// 延时2秒
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
}
}
class Phone4{
public synchronized void send(){
// 延时4秒
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
}
④ 两个对象分别调用,上面两个线程先打印发短信还是打电话?
结果:
打电话
发短信
synchronized 锁的对象是方法的调用者
两个线程用的两把不同锁,而send()方法延时4秒,所以先输出打电话
public class demo05 {
public static void main(String[] args) {
Phone5 phone = new Phone5();
new Thread(()->{
phone.send();
},"A").start();
// 延时2秒
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.call();
},"B").start();
}
}
class Phone5{
public static synchronized void send(){
// 延时4秒
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public static synchronized void call(){
System.out.println("打电话");
}
}
⑤ 两个静态的同步方法,上面两个线程先输出发短信还是打电话?
结果:
发短信
打电话
public class demo06 {
public static void main(String[] args) {
Phone6 phone1 = new Phone6();
Phone6 phone2 = new Phone6();
new Thread(()->{
phone1.send();
},"A").start();
// 延时2秒
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
}
}
class Phone6{
public static synchronized void send(){
// 延时4秒
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public static synchronized void call(){
System.out.println("打电话");
}
}
⑥ 两个静态的同步方法,两个对象分别调用,上面两个线程先输出发短信还是打电话?
结果:
发短信
打电话
加上static,方法变为静态同步方法,此时synchronized锁的对象是Phone的Class对象
public class demo07 {
public static void main(String[] args) {
Phone7 phone = new Phone7();
new Thread(()->{
phone.send();
},"A").start();
// 延时2秒
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.call();
},"B").start();
}
}
class Phone7{
public static synchronized void send(){
// 延时4秒
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
}
⑦ 一个静态同步方法,一个普通方法,上面两个线程先输出发短信还是打电话?
结果:
打电话
发短信
public class demo08 {
public static void main(String[] args) {
Phone8 phone1 = new Phone8();
Phone8 phone2 = new Phone8();
new Thread(()->{
phone1.send();
},"A").start();
// 延时2秒
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
}
}
class Phone8{
public static synchronized void send(){
// 延时4秒
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
}
⑧ 一个静态同步方法,一个普通方法,两个对象调用,上面两个线程先输出发短信还是打电话?
结果:
打电话
发短信
静态同步方法synchronized锁的对象是Class对象
普通同步方法synchronized锁的对象是方法调用者
线程A和线程B的锁是不同的,线程A中send方法延时4秒,所以先输出打电话