目录
1、标准情况下,两个线程先打印哪个
使用synchronized锁
public class Test1 {
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{
//synchronized锁的对象是方法的调用者
//都是phone,因为用的同一把锁,所以谁先拿到谁先执行
public synchronized void sendSms(){
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
}
先发短信后打电话
原因
synchronized锁的对象是方法的调用者,Test1的对象都是phone,因为用的同一把锁,所以谁先拿到谁先执行。
2、sendSms延迟四秒,执行顺序
public synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
结果
依旧是先发短信后打电话
原因
不能解释为A先执行所以先发短信,依旧要围绕锁的原因
3、增加一个普通方法后,先发短信还是先hello;
public class Test2{
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锁的对象是方法的调用者
//都是phone,因为用的同一把锁,所以谁先拿到谁先执行
public synchronized void sendSms(){
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先执行
原因
synchronized锁的对象是方法的调用者,因为hello()方法没有加锁,不需要等待锁。
4、两个对象,两个同步方法,发短信还是打电话
public class Test2{
public static void main(String[] args) {
//两个对象,两个调用者,两把锁
Phone2 phone1 = new Phone2();
Phone2 phone2 = new Phone2();
new Thread(()->{phone1.sendSms();},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{phone2.call();},"B").start();
}
}
class Phone2{
public synchronized void sendSms(){
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");
}
}
原因
synchronized锁的对象是方法的调用者,此时我们有两个对象,phone1和phone2,两者互不影响,又因为发短信的方法延迟了4秒,所以打电话先执行(这讲的有点像高中解数学题了额)。
5.增加两个静态的同步方法
class Phone3{
public static synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public static synchronized void call(){
System.out.println("打电话");
}
}
结果
先发短信,后打电话
原因
前提:synchronized锁的对象是方法的调用者,因为用的同一把锁,所以谁先拿到谁先执行
推导:static是静态,类一加载就有了,锁的是Class,所以依旧是A先拿到先执行发短信
6、两个对象,增加两个静态的同步方法
public class Test3{
public static void main(String[] args) {
//两个对象,两个调用者,两把锁
Phone3 phone1 = new Phone3();
Phone3 phone2 = new Phone3();
new Thread(()->{phone1.sendSms();},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{phone2.call();},"B").start();
}
}
class Phone3{
public static synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public static synchronized void call(){
System.out.println("打电话");
}
}
结果
原因
虽然这里有两个对象,但因为都是static静态方法,所以他们的真正对象都是一样的,其实都是同一个class对象—》Phone3的class全局唯一
7、一个静态同步方法,一个普通同步方法,先打印谁
class Phone4{
public static synchronized void sendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
//普通同步方法
public synchronized void call(){
System.out.println("打电话");
}
}
结果
先打电话后发短信
原因
一个静态同步方法,一个普通同步方法,两个锁的对象不一样,发短信有4秒延迟。
8、一个静态同同步方法,一个普通同步方法,两个对象
public class Test4{
public static void main(String[] args) {
//两个对象,两个调用者,两把锁
Phone4 phone = new Phone4();
new Thread(()->{phone.sendSms();},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{phone.call();},"B").start();
}
}
class Phone4{
public static synchronized void sendSms(){
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");
}
}
结果
原因
这里不说大家应该也明白了。