线程8锁
场景一
package com.myc.lock8;
import java.util.concurrent.TimeUnit;
/**
* 问题1:先执行 call,还是先执行 send?
* 答:call
* 被 synchronized 修饰的方法,锁的对象是方法的调用者,也就是phone
* 先调用的先拿到锁,就会先执行
*/
@SuppressWarnings("all")
public class Demo1 {
public static void main(String[] args) {
Phone phone = new Phone();
new Thread(() ->{
phone.call();
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() ->{
phone.send();
},"B").start();
}
}
class Phone{
//synchronized锁的对象是方法的调用者,也就是Phone的实例
//两个方法使用的是同一个锁,谁先拿到,谁就执行
public synchronized void call(){
System.out.println("打电话");
}
public synchronized void send(){
System.out.println("发短信");
}
}
场景二
package com.myc.lock8;
import java.util.concurrent.TimeUnit;
/**
*问题2:call 方法休眠4秒后,先执行那个call 还是 send
* 答:call
* 被锁的仍是方法的调用者,phone,call 先调用拿到锁,休眠不会释放锁,call 执行完send 才会执行
*
*/
@SuppressWarnings("all")
public class Demo2 {
public static void main(String[] args) {
Phone2 phone = new Phone2();
new Thread(() ->{
try {
phone.call();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() ->{
phone.send();
},"B").start();
}
}
class Phone2{
//synchronized锁的对象是方法的调用者,也就是Phone的实例
//两个方法使用的是同一个锁,谁先拿到,谁就执行
public synchronized void call() throws InterruptedException {
TimeUnit.SECONDS.sleep(4);
System.out.println("打电话");
}
public synchronized void send(){
System.out.println("发短信");
}
}
场景三
package com.myc.lock8;
import java.util.concurrent.TimeUnit;
/**
*问题3:被synchronized 修饰的方法 和普通的方法,谁先被调用
* 答:hello
* call 和 send 需要锁才能执行, hello 不受影响,如果call休眠的时间小于等于4秒,call先执行
*
*/
@SuppressWarnings("all")
public class Demo3 {
public static void main(String[] args) {
Phone3 phone = new Phone3();
new Thread(() ->{
try {
phone.call();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() ->{
phone.send();
},"B").start();
new Thread(() ->{
phone.hello();
},"C").start();
}
}
class Phone3{
public synchronized void call() throws InterruptedException {
TimeUnit.SECONDS.sleep(4);
System.out.println("打电话");
}
public synchronized void send(){
System.out.println("发短信");
}
public void hello(){
System.out.println("说Hello");
}
}
场景四
package com.myc.lock8;
import java.util.concurrent.TimeUnit;
/**
*问题4:被synchronized 修饰的不同方法 先执行send() 还是call()?
* 答:send
* 被锁的仍是方法的调用者,phone1 和 phone2 是两把不同的锁,call休眠的时间长 ,send先执行
*
*/
@SuppressWarnings("all")
public class Demo4 {
public static void main(String[] args) {
Phone4 phone1 = new Phone4();
Phone4 phone2 = new Phone4();
new Thread(() ->{
try {
phone1.call();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() ->{
phone2.send();
},"B").start();
}
}
class Phone4{
public synchronized void call() throws InterruptedException {
TimeUnit.SECONDS.sleep(4);
System.out.println("打电话");
}
public synchronized void send(){
System.out.println("发短信");
}
}
场景五
package com.myc.lock8;
import java.util.concurrent.TimeUnit;
/**
*问题5:两个静态的同步方法,都被Synthronized 修饰,先执行 call 还是 send
* 答:call
* 只要方法被 static 修饰,锁的对象就是 Class模板对象,这个则全局唯一!
* 所以说这里是同一个锁,并不是因为synchronized 这里程序会从上往下依次执行
*
*/
@SuppressWarnings("all")
public class Demo5 {
public static void main(String[] args) {
Phone7 phone = new Phone7();
new Thread(() ->{
try {
phone.call();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() ->{
phone.send();
},"B").start();
}
}
class Phone5{
public static synchronized void call() throws InterruptedException {
TimeUnit.SECONDS.sleep(4);
System.out.println("打电话");
}
public static synchronized void send(){
System.out.println("发短信");
}
}
场景六
package com.myc.lock8;
import java.util.concurrent.TimeUnit;
/**
* 问题6::被synchronized 修饰的普通方法和静态方法 是先send还是 call
* 答案:send
* 解释:只要被static修饰锁的是class模板, 而synchronized 锁的是调用的对象
* 这里是两个锁互不影响,按时间先后执行
*
*/
@SuppressWarnings("all")
public class Demo6 {
public static void main(String[] args) {
Phone6 phone = new Phone6();
new Thread(() ->{
try {
phone.call();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() ->{
phone.send();
},"B").start();
}
}
class Phone6{
public static synchronized void call() throws InterruptedException {
TimeUnit.SECONDS.sleep(4);
System.out.println("打电话");
}
public synchronized void send(){
System.out.println("发短信");
}
}
场景七
package com.myc.lock8;
import java.util.concurrent.TimeUnit;
/**
*问题7:两个不同的对象分别调用两个静态的同步方法,都被Synthronized 修饰,先执行 call 还是 send
* 答:call
* 只要方法被 static 修饰,锁的对象就是 Class模板对象,这个则全局唯一,phone1和phone2用
* 的是同一个锁,并不是因为synchronized 这里程序会从上往下依次执行
*
*/
@SuppressWarnings("all")
public class Demo7 {
public static void main(String[] args) {
Phone7 phone1 = new Phone7();
Phone7 phone2 = new Phone7();
new Thread(() ->{
try {
phone1.call();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() ->{
phone2.send();
},"B").start();
}
}
class Phone7{
public static synchronized void call() throws InterruptedException {
TimeUnit.SECONDS.sleep(4);
System.out.println("打电话");
}
public static synchronized void send(){
System.out.println("发短信");
}
}
场景八
package com.myc.lock8;
import java.util.concurrent.TimeUnit;
/**
* 问题8::一个被static+synchronized 修饰的方法和普通的synchronized方法,先执行send还是call?
* 答案:send
* 解释:只要被static修饰锁的是class模板, 而synchronized 锁的是调用的对象
* 这里是两个锁互不影响,按时间先后执行
*
*/
@SuppressWarnings("all")
public class Demo8 {
public static void main(String[] args) {
Phone8 phone1 = new Phone8();
Phone8 phone2 = new Phone8();
new Thread(() ->{
try {
phone1.call();
} catch (InterruptedException e) {
e.printStackTrace();
}
},"A").start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(() ->{
phone2.send();
},"B").start();
}
}
class Phone8{
public static synchronized void call() throws InterruptedException {
TimeUnit.SECONDS.sleep(4);
System.out.println("打电话");
}
public synchronized void send(){
System.out.println("发短信");
}
}
小结
- 被static + synchronized 修饰的方法锁的是类,被 synchronized 修饰的方法锁的是类的实例,分别调用两种方法,使用的肯定是两把锁,互不影响
- 被static + synchronized 修饰的两种方法,无论几个实例,调用的都是类本身的锁
- 只被 synchronized 修饰的两种方法 ,一个实例调用是一把锁,两个实例调用就是两个不同的锁

浙公网安备 33010602011771号