一 对象锁和类锁的关系
/* * 对象锁和【类锁】 全局锁的关系? 对象锁是用于对象实例方法,或者一个对象实例上的 this 类锁是用于类的静态方法或者一个类的class对象上的。 Ag.class 我们知道,类的对象实例可以有很多个,但是每个类只有一个class对象, 所以不同对象实例的对象锁是互不干扰的,但是每个类只有一个类锁。 */
对象锁, 不同对象。
public class SynchrDemo { public static void main(String[] args) { Thread1 thread1 = new Thread1(); Thread1 thread2 = new Thread1(); thread1.start(); thread2.start(); } } class Ag{ public void show(){ // this 是当前对象的实例,由于新建两个对象,不是同一对象。所以这里是锁不住的。 代码快的方式,比修饰在方法上更细化控制。 synchronized (this) { for (int i = 0; i < 4; i++) { System.out.println(Thread.currentThread().getName() + " i=" + i); } } } } class Thread1 extends Thread{ @Override public void run() { //这里是新建对象 主方法中new了两个thread,就是new了两个Ag对象 Ag ag = new Ag(); ag.show(); } }
关键字修饰方法
public class SynchrDemo { public static void main(String[] args) { Thread1 thread1 = new Thread1(); Thread1 thread2 = new Thread1(); thread1.start(); thread2.start(); } } class Ag{ // 这次修饰的是方法,范围比代码块要大,意味着在这个区域内,锁生效的时候,都是在阻塞,其他线程的等待时间就会增加。 // 这次实验的非同一对象,所以这里的锁是不起作用的。 public synchronized void show(){ for (int i = 0; i < 4; i++) { System.out.println(Thread.currentThread().getName() + " i=" + i); } } } class Thread1 extends Thread{ @Override public void run() { //这里是新建对象 主方法中new了两个thread,就是new了两个Ag对象 Ag ag = new Ag(); ag.show(); } }
二 对象锁 同一对象
package com.aaa.threaddemo; /* * 一 Java中的关键字 synchronized 是啥? * synchronized是Java提供的一个并发控制的关键字。 * * 用法:同步方法 和 同步代码块。 * 可以修饰方法 也可以 修饰代码块。 * * 作用: 被synchronized修饰的代码块及方法,在同一时间,只能被单个线程访问。【保证线程安全】 1 修饰方法和代码块有什么不同? 二者的结果是一样的 修饰方法时,作用域是整个方法,控制的范围大。 synchronized 代码块 可控制具体的作用域,更精准控制提高效率。 减少阻塞带来的时间问题。 2 同步锁的给谁用的? 同步锁基于对象,只要锁的来源一致,即可达到同步的作用。 所以,但对象不一样,则不能达到同步效果。 3 synchronized修饰方法,代码块,锁未释放,此时,其他线程调用同一对象的其他被synchronized修饰的方法,代码块,会如何? 当线程 A 调用某对象的synchronized 方法 或者 synchronized 代码块时,若同步锁未释放, 其他线程调用同一对象的其他 synchronized 方法 或者 synchronized 代码块时将被阻塞,直至线程 A 释放该对象的同步锁。(注意:重点是其他) 4 调用非synchronized方法 ,代码快呢? 当线程 A 调用某对象的synchronized 方法 或者 synchronized 代码块时,无论同步锁是否释放, 其他线程调用同一对象的其他 非 synchronized 方法 或者 非 synchronized 代码块时可立即调用。 5 全局锁如何实现? 全局锁: 锁住整个 Class,而非某个对象或实例。1-4都是实例锁 实现: 静态 synchronized 方法 static 声明的方法为全局方法,与对象实例化无关, 所以 static synchronized 方法为全局同步方法,与对象实例化无关。 6 synchronized 具体 Class 的代码块? synchronized (Ag.class) 获得的同步锁是全局的, static synchronized 获得的同步锁也是全局的,同一个锁,所以达到同步效果。 7 对象锁和【类锁】 全局锁的关系? 对象锁是用于对象实例方法,或者一个对象实例上的 this 类锁是用于类的静态方法或者一个类的class对象上的。 Ag.class 我们知道,类的对象实例可以有很多个,但是每个类只有一个class对象, 所以不同对象实例的对象锁是互不干扰的,但是每个类只有一个类锁。 * * */ /* * 对象锁和【类锁】 全局锁的关系? 对象锁是用于对象实例方法,或者一个对象实例上的 this 类锁是用于类的静态方法或者一个类的class对象上的。 Ag.class 我们知道,类的对象实例可以有很多个,但是每个类只有一个class对象, 所以不同对象实例的对象锁是互不干扰的,但是每个类只有一个类锁。 */ public class SynchrDemo { public static void main(String[] args) { // 改造后,可以确保是同一对象 验证 synchronized 是否生效 Ag ag = new Ag(); Thread1 thread1 = new Thread1(ag); Thread1 thread2 = new Thread1(ag); thread1.start(); thread2.start(); } } class Ag{ // 这次修饰的是方法,范围比代码块要大,意味着在这个区域内,锁生效的时候,都是在阻塞,其他线程的等待时间就会增加。 // 这次实验的同一对象,所以这里的锁是起作用的。 public synchronized void show(){ for (int i = 0; i < 4; i++) { System.out.println(Thread.currentThread().getName() + " i=" + i); } } } /* * 改造一些 对象的生成,确保在Thread1 中获得的是同一对象 */ class Thread1 extends Thread{ private Ag mag; public Thread1(Ag ag) { mag = ag; } @Override public void run() { mag.show(); } }
验证代码快的方式?
public class SynchrDemo { public static void main(String[] args) { // 改造后,可以确保是同一对象 验证 synchronized 是否生效 Ag ag = new Ag(); Thread1 thread1 = new Thread1(ag); Thread1 thread2 = new Thread1(ag); thread1.start(); thread2.start(); } } class Ag{ // 这次修饰的是方法,范围比代码块要大,意味着在这个区域内,锁生效的时候,都是在阻塞,其他线程的等待时间就会增加。 // 这次实验的同一对象,所以这里的锁是起作用的。 public void show(){ synchronized (this) { for (int i = 0; i < 4; i++) { System.out.println(Thread.currentThread().getName() + " i=" + i); } // this 就是当前的对象,我们现在获得就是同一对象 System.out.println(this); } } } /* * 改造一些 对象的生成,确保在Thread1 中获得的是同一对象 */ class Thread1 extends Thread{ private Ag mag; public Thread1(Ag ag) { mag = ag; } @Override public void run() { mag.show(); } }
三 类锁? 非同一对象
/* * * 类锁,全局锁如何实现? 全局锁: 锁住整个 Class,而非某个对象或实例 实现: 1 在静态方法上用 synchronized 关键字修饰 2 在代码块上使用 类名.class static 声明的方法为全局方法,与对象实例化无关, 所以 static synchronized 方法为全局同步方法,与对象实例化无关。 */ public class SynchrDemo { public static void main(String[] args) { //非同一对象 Thread2 thread1 = new Thread2(); Thread2 thread2 = new Thread2(); thread1.start(); thread2.start(); } } class Ag{ public void show(){ // 使用 synchronized() 方法,将锁控制在代码快上。 synchronized (Ag.class) { for (int i = 0; i < 4; i++) { System.out.println(Thread.currentThread().getName() + " i=" + i); } // this 就是当前的对象,我们现在获得就是非同一对象 System.out.println(this); } } } class Thread2 extends Thread{ @Override public void run() { Ag ag = new Ag(); ag.show(); } }
测试 关键字修饰 static 方法
public class SynchrDemo { public static void main(String[] args) { //非同一对象 Thread2 thread1 = new Thread2(); Thread2 thread2 = new Thread2(); thread1.start(); thread2.start(); } } class Ag{ // 静态的方法 被synchronized 修饰后, 锁住的是 类。 public static synchronized void show(){ for (int i = 0; i < 4; i++) { System.out.println(Thread.currentThread().getName() + " i=" + i); } } } class Thread2 extends Thread{ @Override public void run() { Ag ag = new Ag(); ag.show(); } }