深入理解synchronized 八锁现象(2-7的第一个方法都延迟四秒)
同一对象
1.同一对象的两个线程,调用一个类的两个加锁方法
锁的对象是方法的调用者,这时因为只有一个调用者,所以输出结果按锁的方法从上到下执行
public class Test1 {
public static void main(String[] args) {
Phone p = new Phone();
new Thread(()->{
p.SendSms();
},"A").start();
//捕获
try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
new Thread(()->{
p.call();
},"B").start();
}
}
class Phone{
public synchronized void SendSms(){
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
}
先输出发短信,再输出打电话
2.同一对象的两个线程,调用一个类的两个加锁方法,在第一个加锁方法上加上等待4秒
锁的对象是方法的调用者,这时因为只有一个调用者,所以输出结果按锁的方法从上到下执行
public class Test1 {
public static void main(String[] args) {
Phone p = new Phone();
new Thread(()->{
p.SendSms();
},"A").start();
//捕获
try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
new Thread(()->{
p.call();
},"B").start();
}
}
class Phone{
public synchronized void SendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
}
4秒后输出 发短信 一秒后输出打电话
3.同一对象的两个线程,调用一个类一个加锁方法一个不加锁方法,其中加锁方法等待4秒
hello 方法没加锁 不受锁限制 因为发短信那个方法等待4秒,所以先运行hello
public class Test34 {
public static void main(String[] args) {
Phone2 p = new Phone2();
new Thread(()->{
p.SendSms();
},"A").start();
//捕获
try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
new Thread(()->{
p.hello();
},"B").start();
}
}
class Phone2{
public synchronized void SendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public void hello(){
System.out.println("hello");
}
}
先输出hello 四秒后输出发短信
5. 同一对象两个线程,调用一个类的两个加锁静态方法,第一个加锁方法等待四秒
static是类一加载就有的,这时锁的是一整个class,而方法因为锁,所以从上到下执行
public class Test56 {
public static void main(String[] args) {
Phone3 p3= new Phone3();
new Thread(()->{
p3.SendSms();
},"A").start();
//捕获
try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
new Thread(()->{
p3.call();
},"B").start();
}
}
class Phone3{
public static synchronized void SendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public static synchronized void call(){
System.out.println("打电话");
}
}
四秒后输出发短信,如输出打电话
7.同一对象两个线程,调用一个类的一个加锁静态方法,第二个方法是普通加锁方法,第一个加锁方法等待四秒
这时两个方法锁的对象是不一样的,第一个锁的是class,第二个锁的方法,所以两个方法没联系,先输出执行快的即打电话
public class Test78 {
public static void main(String[] args) {
Phone4 p4= new Phone4();
new Thread(()->{
p4.SendSms();
},"A").start();
//捕获
try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
new Thread(()->{
p4.call();
},"B").start();
}
}
class Phone4{
public static synchronized void SendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("发短信");
}
//普通锁
public synchronized void call(){
System.out.println("打电话");
}
}
两个对象
4.两个对象,各调用同一个类的两个加锁方法,其中第一个加锁方法等待四秒
这时候因为有两个对象,所以其实是两把锁,所以先输出打电话
public class Test34 {
public static void main(String[] args) {
Phone2 p1 = new Phone2();
Phone2 p2 = new Phone2();
new Thread(()->{
p1.SendSms();
},"A").start();
//捕获
try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
new Thread(()->{
p2.call();
},"B").start();
}
}
class Phone2{
public synchronized void SendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public synchronized void call(){
System.out.println("打电话");
}
}
先输出打电话 四秒后输出发短信
6. 两个对象,调用一个类的两个加锁静态方法,第一个加锁方法等待四秒
这其实是第四个方法的加深版
从第四个可以知道:
static是类一加载就有的,这时锁的是一整个class,而方法因为锁,所以从上到下执行
这时候等四秒先输出发短信
public class Test56 {
public static void main(String[] args) {
Phone3 p3= new Phone3();
Phone3 p4= new Phone3();
new Thread(()->{
p3.SendSms();
},"A").start();
//捕获
try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
new Thread(()->{
p4.call();
},"B").start();
}
}
class Phone3{
public static synchronized void SendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("发短信");
}
public static synchronized void call(){
System.out.println("打电话");
}
}
四秒后输出发短信,然后输出打电话
8. 两个对象,调用一个类的一个加锁静态方法,第二个方法是普通加锁方法,第一个加锁方法等待四秒
跟方法7类似
这时两个方法锁的对象是不一样的,第一个锁的是class,第二个锁的方法,所以两个方法没联系,不管你几个对象,都先输出执行快的即打电话
public class Test78 {
public static void main(String[] args) {
Phone4 p4= new Phone4();
Phone4 p5= new Phone4();
new Thread(()->{
p4.SendSms();
},"A").start();
//捕获
try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
new Thread(()->{
p5.call();
},"B").start();
}
}
class Phone4{
public static synchronized void SendSms(){
try {
TimeUnit.SECONDS.sleep(4);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("发短信");
}
//普通锁
public synchronized void call(){
System.out.println("打电话");
}
}