文章目录
八锁现象彻底理解锁
- 如何判断锁的是谁,深刻理解锁
- 关于锁的八个核心问题
先执行sendMsg还是callbaby
/**
* 正常情况下是先执行sendMeg还是callbaby
*/
/**
* 正常情况下是先执行sendMeg还是callbaby
*/
public class Test1 {
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(()->{
phone.sendMes();
},"A线程").start();
// 休眠
try {
// 最好使用这个工具类的sleep
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.call();
},"B线程").start();
}
}
class Phone {
public synchronized void sendMes() {
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("send message");
}
public synchronized void call() {
System.out.println("call baby");
}
}
- 结果:先调用sendMes再调用call
- 原因:
- synchronized锁的对象是方法的调用者
- call和sendMes被调用的都是phone,所以用的是同一把锁,谁先拿到谁先执行
增加一个普通方法
public class Test1 {
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(()->{
phone.sendMes();
},"A线程").start();
// 休眠
try {
// 最好使用这个工具类的sleep
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.hello();
},"B线程").start();
}
}
class Phone {
public synchronized void sendMes() {
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("send message");
}
public synchronized void call() {
System.out.println("call baby");
}
public void hello() {
System.out.println("hello");
}
}
- hello没有锁,不是同步方法,不受锁的影响
创建两个对象
public class Test1 {
public static void main(String[] args) {
Phone phone = new Phone();
Phone phone2 = new Phone();
new Thread(()->{
phone.sendMes();
},"A线程").start();
// 休眠
try {
// 最好使用这个工具类的sleep
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B线程").start();
}
}
class Phone {
public synchronized void sendMes() {
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("send message");
}
public synchronized void call() {
System.out.println("call baby");
}
public void hello() {
System.out.println("hello");
}
}
- 有两个对象,有两把锁
增加static关键字
public class Test1 {
public static void main(String[] args) {
Phone phone = new Phone();
Phone phone2 = new Phone();
new Thread(()->{
phone.sendMes();
},"A线程").start();
// 休眠
try {
// 最好使用这个工具类的sleep
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B线程").start();
}
}
class Phone {
public static synchronized void sendMes() {
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("send message");
}
public static synchronized void call() {
System.out.println("call baby");
}
public void hello() {
System.out.println("hello");
}
}
- static静态方法,类一加载就有了,锁的是class
- 虽然是两个对象,但是锁的是class(类模板只有一个),那就只有一把锁
静态同步方法和非静态同步方法
public class Test1 {
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(()->{
phone.sendMes();
},"A线程").start();
// 休眠
try {
// 最好使用这个工具类的sleep
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.call();
},"B线程").start();
}
}
class Phone {
public static synchronized void sendMes() {
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("send message");
}
public synchronized void call() {
System.out.println("call baby");
}
public static void hello() {
System.out.println("hello");
}
}
- 两个方法是不同的锁
锁总结
- 锁class
- 锁具体对象
- 锁住class,创建出来的对象是同一把锁
- 锁class和锁对象,不是同一把锁