现象一
多个线程使用一把锁,也就是调用同一个对象,顺序执行。
“被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{
public synchronized void sendSms() {
System.out.println("发短信");
}
public synchronized void call() {
System.out.println("打电话");
}
}
执行结果:发短信 打电话
现象二
多个线程使用同一把锁,其中一个锁方法里存在阻塞,顺序执行。
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{
public synchronized void sendSms() {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call() {
System.out.println("打电话");
}
}
执行结果:发短信 打电话
现象三
多个线程中既有锁方法,也有普通方法,会随机执行。
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{
public synchronized void sendSms() {
//此阻塞时间长短会对结果产生一定影响,但是理论不变
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public void call() {
System.out.println("打电话");
}
}
执行结果:发短信 打电话
现象四
多个线程调用多个对象,多个线程使用多把锁,会随机执行。
“Synchronized锁的是方法调用者(即对象),两个线程调用两个不同的对象,所以互不干扰。”
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(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call() {
System.out.println("打电话");
}
}
执行结果:发短信 打电话
现象五
Class锁,static和Synchronized修饰的方法。
多个线程使用一个对象(一把锁)但是被static修饰,所以锁的是class文,全局只有一个class文,会顺序执行。
“被Synchronized和static同时修饰的方法,锁的对象是类的class对象,是唯一的一把锁。线程之间是顺序执行。“
锁class和锁对象的区别:
- Class锁:类模板,只有一个;
- 对象锁:通过类模板可以new多个对象。
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锁的是实例对象(即方法的调用者)
//static 和 synchronized同时修饰 锁的是class
public static synchronized void sendSms() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public static synchronized void call() {
System.out.println("打电话");
}
}
执行结果:发短信 打电话
现象六
Class锁,static和synchronized修饰的方法。
多个线程使用多个对象(多个锁),可是被static修饰,即锁的是class文,全局只有一个class文,会顺序执行。
public class Test1 {
public static void main(String[] args) {
Phone phone1 = new Phone();
Phone phone2 = new Phone();
new Thread(()->{
phone1.sendSms();
},"A").start();
//睡眠
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
}
}
class Phone{
//synchronized锁的是实例对象(即方法的调用者)
//static 和 synchronized同时修饰 锁的是class
public static synchronized void sendSms() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public static synchronized void call() {
System.out.println("打电话");
}
}
执行结果:发短信 打电话
现象七
一个静态同步方法 ,一个普通同步方法。
多个线程去操作同一个对象,会先执行普通同步方法。
“这里虽然只有“一个对象”,但是这“一个对象”调用的方法不同,所以两个线程分别使用两把锁。”
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锁的是实例对象(即方法的调用者)
//static 和 synchronized同时修饰 锁的是class
public static synchronized void sendSms() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call() {
System.out.println("打电话");
}
}
执行结果:打电话 发短信
现象八
两个静态同步方法,两个对象。
顺序执行。
public class Test1 {
public static void main(String[] args) {
Phone phone1 = new Phone();
Phone phone2 = new Phone();
new Thread(()->{
phone1.sendSms();
},"A").start();
//睡眠
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(()->{
phone2.call();
},"B").start();
}
}
class Phone{
//synchronized锁的是实例对象(即方法的调用者)
//static 和 synchronized同时修饰 锁的是class
public static synchronized void sendSms() {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public static synchronized void call() {
System.out.println("打电话");
}
}
执行结果:发短信 打电话
总结:
//被synchronized修饰的方法,锁的对象是实例对象(即方法的调用者)。
//被static synchronized修饰的方法,锁的对象就是class模板对象,这个是全局唯一的。
- synchronized修饰的,多个线程调用单个对象(一把锁) 顺序执行
- synchronized修饰的,多个线程调用多个对象(多把锁) 随机执行
(注意发短信线程阻塞时间不同会影响结果,阻塞时间长,后执行,反之亦然,而单个对象,即一把锁,无论发短信线程阻塞时间怎 么设置,都是顺序执行)
//因为synchronized修饰的,锁的是实例对象(方法调用者),所以单个对象的时候谁先调用就谁先拿到锁先执行,而多个对象的时候就看cpu调度,随机执行。
3.static synchronized同时修饰的,多个线程调用单个对象,顺序执行。
4.static synchronized同时修饰的,多个线程调用多个对象,顺序执行。
//因为static synchronized同时修饰的,锁的是class文,全局唯一,所以单个对象或多个对象调用的时候都是顺序执行。