1.八锁现象
如何判断锁的是谁?永远的知道什么锁,锁到底锁的是谁?
深刻理解我们的锁!
1.标准情况下,两个线程先打印.是先发短信还是打电话?
public class Teat01 {
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(()->{
phone.sendSms();
},"A").start();
try {
//捕获
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.call();
},"B").start();
}
}
class Phone{
public synchronized void sendSms(){
System.out.println("sendSms");
}
public synchronized void call(){
System.out.println("call");
}
}
结果:第一个是发短信第二个是打电话.是固定不变的.
2.sendSms延迟四秒,同样执行程序是先执行发短信还是打电话
public class Teat01 {
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(()->{
phone.sendSms();
},"A").start();
try {
//捕获
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.call();
},"B").start();
}
}
class Phone{
public synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);//再给A线程延迟4秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sendSms");
}
public synchronized void call(){
System.out.println("call");
}
结果如下:
还是等了A线程执行后,再执行call
3.在Phone2中添加一个方法,输出为hello,不是同步锁,B线程,调用hello方法,请问是先执行发短信还是输出hello
public class Test02 {
public static void main(String[] args) {
Phone2 phone = new Phone2();
new Thread(()->{
phone.sendSms();
},"A").start();
try {
//捕获
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone.hello();
},"B").start();
}
}
class Phone2{
//synchronized 锁的对象,是方法的调用者!上面代码new了一个对象,开了两个线程.所以用的是同一把锁(phone的锁)
//谁先拿到谁就执行
public synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sendSms");
}
public synchronized void call(){
System.out.println("call");
}
//这里没有锁,没有同步方法,不受锁的影响.
public void hello(){
System.out.println("Hello");
}
小结论:这里没有锁,没有同步方法,不受锁的影响.所以延迟执行的,自然没有普通方法执行快
4.同上代码:增加一个对象,两个对象,两个同步方法,同时执行
//两个对象
Phone2 phone = new Phone2();
Phone2 phone2 = new Phone2();
new Thread(()->{
phone.sendSms();
},"A").start();
new Thread(()->{
phone2.call();
},"B").start();
结果为:打电话先执行,原因是两个对象两把锁互不影响,由于,发短信延迟了4秒,所以毋庸置疑,call先于sendSms
5.增加两个静态的同步方法 +Static
同上代码:在synchronized前面加上static,请问那个先执行
public static synchronized void call(){
System.out.println("call");
}
public static synchronized void sendSms(){}
结果:
原因:static为静态方法,和类加载时一起执行的.和synchronized现在锁的不是调用者,而是模板
如:Class phone3Class = Phone3.class;锁这个Class模板,Phone3唯一的一个Class对象
6.两个对象!增加两个静态的同步方法,是先执行发短信还是打电话?
hone3 phone2 = new Phone3();
new Thread(()->{
phone2.call();
},"B").start();
原因:两个对象Class模板只有一个,与两个对象无关了,Static锁的是Class,所有说还是发短信在前面
7.一个静态同步方法,和一个普通同步方法
代码变化:
Phone4 phone = new Phone4();
public static synchronized void sendSms(){//锁的是Class类模板
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sendSms");
public synchronized void hello(){
System.out.println("Hello");
}
原因:首先静态同步方法锁的是Class模板,但是该方法有延时,而普通的同步方法锁的是phone的调用对象,两个方法不是用的一把锁所以先走Hello方法
8.一个静态同步方法,和一个普通同步方法,两个对象
代码:
package com.lock8;
import java.util.concurrent.TimeUnit;
/**
* 8锁就是关于锁的八个问题
* 1.标准情况下,两个线程先打印.是先发短信还是打电话?结果:第一个是发短信第二个是打电话.是固定不变的.
* 2.sendSms延迟四秒,同样执行程序是先执行发短信还是打电话
* 3.再Phone2中添加一个方法,输出为hello,不是同步锁,B线程,调用hello方法,请问是先执行发短信还是输出hello
* 4.两个对象,两个同步方法,同时执行
* 5.增加两个静态的同步方法 +Static:
* 6.两个对象!增加两个静态的同步方法,是先执行发短信还是打电话?
* 7.一个静态同步方法,和一个普通同步方法,一个对象
* 8.一个静态同步方法,和一个普通同步方法,两个对象
*/
public class Test04 {
public static void main(String[] args) {
//两个对象
Phone4 phone = new Phone4();
Phone4 phone1 = new Phone4();
new Thread(()->{
phone.sendSms();
},"A").start();
try {
//捕获
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone1.call();
},"B").start();
}
}
//Phone3唯一的一个Class对象
class Phone4{
//static 静态方法
//类一加载就有了,Class 模板
//synchronized 锁的对象,是方法的调用者!
public static synchronized void sendSms(){//锁的是Class类模板
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sendSms");
Class<Phone3> phone3Class = Phone3.class;
}
public synchronized void call(){
System.out.println("call");
}
public synchronized void hello(){
System.out.println("Hello");
}
}
原因:两个锁的对象不一样,而发短信有延迟,所以打电话先执行
小结:
一个是new 一个是static
new this 具体的一个手机
static Class 唯一的一个模板