10.JUC线程高级-线程八锁

简介: 所谓线程八锁实际上对应于是否加上synchronized,是否加上static等8种常见情况,代码如下:1.两个普通同步方法,两个线程,标准打印,结果:one twopublic class TestThread8Monitor { pub...

所谓线程八锁实际上对应于是否加上synchronized,是否加上static等8种常见情况,代码如下:

1.两个普通同步方法,两个线程,标准打印,结果:one two

public class TestThread8Monitor {
    public static void main(String[] args) {
        final Number number = new Number();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                number.getOne();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                number.getTwo();
            }
        }).start();
    }
}
class Number{
    public synchronized void getOne(){
        System.out.println("one");
    }
    public synchronized void getTwo(){
        System.out.println("Two");
    }
}

2.新增Thread.sleep()给getOne(),结果:one two

public class TestThread8Monitor {
    public static void main(String[] args) {
        final Number number = new Number();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                number.getOne();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                number.getTwo();
            }
        }).start();
    }
}
class Number{
    public synchronized void getOne(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("one");
    }
    public synchronized void getTwo(){
        System.out.println("Two");
    }
}

3.新增普通方法getThree(),结果:three one two

public class TestThread8Monitor {
    public static void main(String[] args) {
        final Number number = new Number();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                number.getOne();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                number.getTwo();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                number.getThree();
            }
        }).start();
    }
}
class Number{
    public synchronized void getOne(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("one");
    }
    public synchronized void getTwo(){
        System.out.println("Two");
    }
    public void getThree(){
        System.out.println("Three");
    }
}

4.两个普通同步方法,两个对象,结果:two one

public class TestThread8Monitor {
    public static void main(String[] args) {
        final Number number1 = new Number();
        final Number number2 = new Number();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                number1.getOne();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                number2.getTwo();
            }
        }).start();
        
    }
}
class Number{
    public synchronized void getOne(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("one");
    }
    public synchronized void getTwo(){
        System.out.println("Two");
    }
}

5.修改getOne()为静态同步方法,结果:two one

public class TestThread8Monitor {
    public static void main(String[] args) {
        final Number number1 = new Number();
        final Number number2 = new Number();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                number1.getOne();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                number2.getTwo();
            }
        }).start();
        
    }
}
class Number{
    public static synchronized void getOne(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("one");
    }
    public synchronized void getTwo(){
        System.out.println("Two");
    }
}

6.修改两个方法均为静态同步方法,一个对象,结果:one two

public class TestThread8Monitor {
    public static void main(String[] args) {
        final Number number1 = new Number();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                number1.getOne();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                number1.getTwo();
            }
        }).start();
        
    }
}
class Number{
    public static synchronized void getOne(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("one");
    }
    public static synchronized void getTwo(){
        System.out.println("Two");
    }
}

7.一个静态同步方法,一个非静态同步方法,两个对象,结果:two one

public class TestThread8Monitor {
    public static void main(String[] args) {
        final Number number1 = new Number();
        final Number number2 = new Number();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                number1.getOne();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                number2.getTwo();
            }
        }).start();
        
    }
}
class Number{
    public static synchronized void getOne(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("one");
    }
    public  synchronized void getTwo(){
        System.out.println("Two");
    }
}

8.两个静态同步方法,两个对象,结果:one two

public class TestThread8Monitor {
    public static void main(String[] args) {
        final Number number1 = new Number();
        final Number number2 = new Number();
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                number1.getOne();
            }
        }).start();
        new Thread(new Runnable() {
            @Override
            public void run() {
                number2.getTwo();
            }
        }).start();
        
    }
}
class Number{
    public static synchronized void getOne(){
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("one");
    }
    public static synchronized void getTwo(){
        System.out.println("Two");
    }
}

以上就是线程的八种常见的情况,线程八锁的关键在于:

非静态方法的锁默认为this,静态方法的锁为对应的class实例(这里是Number.class)
某一个时刻内,只能有一个线程持有锁,无论有几个方法。

总结:

①一个对象里面如果有多个synchronized方法,某一个时刻内,只要一个线程去调用其中的一个synchronized方法了,其他的线程都只能等待,换句话说,某一时刻内,只能有唯一一个线程去访问这些synchronized方法。

②锁的是当前对象this,被锁定后,其他线程都不能进入到当前对象的其他的synchronized方法。

③加个普通方法后发现和同步锁无关。

④换成静态同步方法后,情况又变化

⑤所有的非静态同步方法用的都是同一把锁 -- 实例对象本身,也就是说如果一个实例对象的非静态同步方法获取锁后,该实例对象的其他非静态同步方法必须等待获取锁的方法释放锁后才能获取锁,可是别的实例对象的非静态同步方法因为跟该实例对象的非静态同步方法用的是不同的锁,所以毋须等待该实例对象已经取锁的非静态同步方法释放锁就可以获取他们自己的锁。

⑥所有的静态同步方法用的也是同一把锁 -- 类对象本身,这两把锁是两个不同的对象,所以静态同步方法与非静态同步方法之间不会有竞争条件。但是一旦一个静态同步方法获取锁后,其他的静态同步方法都必须等待该方法释放锁后才能获取锁,而不管是同一个实例对象的静态同步方法之间,还是不同的实例对象的静态同步方法之间,只要它们是同一个实例对象

目录
相关文章
|
5月前
|
缓存 安全 Java
JUC系列之《CountDownLatch:同步多线程的精准发令枪 》
CountDownLatch是Java并发编程中用于线程协调的同步工具,通过计数器实现等待机制。主线程等待多个工作线程完成任务后再继续执行,适用于资源初始化、高并发模拟等场景,具有高效、灵活、线程安全的特点,是JUC包中实用的核心组件之一。
|
5月前
|
设计模式 缓存 安全
【JUC】(6)带你了解共享模型之 享元和不可变 模型并初步带你了解并发工具 线程池Pool,文章内还有饥饿问题、设计模式之工作线程的解决于实现
JUC专栏第六篇,本文带你了解两个共享模型:享元和不可变 模型,并初步带你了解并发工具 线程池Pool,文章中还有解决饥饿问题、设计模式之工作线程的实现
326 2
|
5月前
|
Java 测试技术 API
【JUC】(1)带你重新认识进程与线程!!让你深层次了解线程运行的睡眠与打断!!
JUC是什么?你可以说它就是研究Java方面的并发过程。本篇是JUC专栏的第一章!带你了解并行与并发、线程与程序、线程的启动与休眠、打断和等待!全是干货!快快快!
840 2
|
5月前
|
设计模式 消息中间件 安全
【JUC】(3)常见的设计模式概念分析与多把锁使用场景!!理解线程状态转换条件!带你深入JUC!!文章全程笔记干货!!
JUC专栏第三篇,带你继续深入JUC! 本篇文章涵盖内容:保护性暂停、生产者与消费者、Park&unPark、线程转换条件、多把锁情况分析、可重入锁、顺序控制 笔记共享!!文章全程干货!
395 1
|
10月前
|
存储 缓存 安全
JUC并发—11.线程池源码分析
本文主要介绍了线程池的优势和JUC提供的线程池、ThreadPoolExecutor和Excutors创建的线程池、如何设计一个线程池、ThreadPoolExecutor线程池的执行流程、ThreadPoolExecutor的源码分析、如何合理设置线程池参数 + 定制线程池。
JUC并发—11.线程池源码分析
|
安全 Java 调度
Java编程时多线程操作单核服务器可以不加锁吗?
Java编程时多线程操作单核服务器可以不加锁吗?
286 2
|
并行计算 安全 Java
Python GIL(全局解释器锁)机制对多线程性能影响的深度分析
在Python开发中,GIL(全局解释器锁)一直备受关注。本文基于CPython解释器,探讨GIL的技术本质及其对程序性能的影响。GIL确保同一时刻只有一个线程执行代码,以保护内存管理的安全性,但也限制了多线程并行计算的效率。文章分析了GIL的必要性、局限性,并介绍了多进程、异步编程等替代方案。尽管Python 3.13计划移除GIL,但该特性至少要到2028年才会默认禁用,因此理解GIL仍至关重要。
1134 16
Python GIL(全局解释器锁)机制对多线程性能影响的深度分析
|
供应链 安全 NoSQL
PHP 互斥锁:如何确保代码的线程安全?
在多线程和高并发环境中,确保代码段互斥执行至关重要。本文介绍了 PHP 互斥锁库 `wise-locksmith`,它提供多种锁机制(如文件锁、分布式锁等),有效解决线程安全问题,特别适用于电商平台库存管理等场景。通过 Composer 安装后,开发者可以利用该库确保在高并发下数据的一致性和安全性。
241 6
|
存储 缓存 安全
【Java面试题汇总】多线程、JUC、锁篇(2023版)
线程和进程的区别、CAS的ABA问题、AQS、哪些地方使用了CAS、怎么保证线程安全、线程同步方式、synchronized的用法及原理、Lock、volatile、线程的六个状态、ThreadLocal、线程通信方式、创建方式、两种创建线程池的方法、线程池设置合适的线程数、线程安全的集合?ConcurrentHashMap、JUC
【Java面试题汇总】多线程、JUC、锁篇(2023版)
|
Java 关系型数据库 MySQL
【JavaEE“多线程进阶”】——各种“锁”大总结
乐/悲观锁,轻/重量级锁,自旋锁,挂起等待锁,普通互斥锁,读写锁,公不公平锁,可不可重入锁,synchronized加锁三阶段过程,锁消除,锁粗化

热门文章

最新文章