多线程编程之线程的同步机制(下): Synchronized同步代码块

简介: 上一篇文章讲了多线程编程中Synchronized同步方法的相关内容,Synchronized除了同步方法之外还可以同步语句块,这篇文章就介绍Synchronized如何同步语句块。

1 前言


上一篇文章讲了多线程编程中Synchronized同步方法的相关内容,Synchronized除了同步方法之外还可以同步语句块,这篇文章就介绍Synchronized如何同步语句块。


2 正文


1、Synchronized同步方法的缺点


在介绍Synchronized同步语句块之前,先来说说Synchronized同步方法的缺点。先看代码:


public class Demo9 {
    public static void main(String[] args) throws InterruptedException {
        Demo9Service service = new Demo9Service();
        Thread t1 = new Demo9ThreadA(service);
        t1.setName("A");
        Thread t2 = new Demo9ThreadA(service);
        t2.setName("B");
        t1.start();
        t2.start();
        Thread.sleep(20000);
        long start = Demo9Untils.start1 > Demo9Untils.start2 ? Demo9Untils.start2 : Demo9Untils.start1;
        long end = Demo9Untils.end1 > Demo9Untils.end2 ? Demo9Untils.end1 : Demo9Untils.end2;
        System.out.println("总耗时:" + (end - start) / 1000 + "秒");
    }
}
class Demo9Untils{
    static long start1;
    static long start2;
    static long end1;
    static long end2;
}
class Demo9Service{
    synchronized public void foo(){
        try{
            System.out.println("开始任务");
            Thread.sleep(5000);
            System.out.println("长时任务处理完成,线程" + Thread.currentThread().getName());
            System.out.println("结束任务");
        }catch(InterruptedException e){
            e.printStackTrace();
        }
    }
}
class Demo9ThreadA extends Thread{
    public Demo9Service service;
    public Demo9ThreadA(Demo9Service service){
        this.service = service;
    }
    @Override
    public void run() {
        Demo9Untils.start1 = System.currentTimeMillis();
        service.foo();
        Demo9Untils.end1 = System.currentTimeMillis();
    }
}
class Demo9ThreadB extends Thread{
    public Demo9Service service;
    public Demo9ThreadB(Demo9Service service){
        this.service = service;
    }
    @Override
    public void run() {
        Demo9Untils.start2 = System.currentTimeMillis();
        service.foo();
        Demo9Untils.end2 = System.currentTimeMillis();
    }
}
复制代码


结果:


d228641caa3d4c00b125c191446d4d98~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


2、Synchronized同步代码块


再来看看synchronized同步代码块的代码:


public class Demo10 {
    public static void main(String[] args) {
        Demo10Service service = new Demo10Service();
        Thread t1 = new Demo10Thread(service);
        t1.setName("A");
        t1.start();
        Thread t2 = new Demo10Thread(service);
        t2.setName("B");
        t2.start();
    }
}
class Demo10Service{
    public void foo(){
        try {
            synchronized (this) {
                System.out.println(Thread.currentThread().getName() + "开始于" + System.currentTimeMillis());
                Thread.sleep(2000);
                System.out.println(Thread.currentThread().getName() + "结束于" + System.currentTimeMillis());
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}
class Demo10Thread extends Thread{
    private Demo10Service service;
    public Demo10Thread(Demo10Service service){
        this.service = service;
    }
    @Override
    public void run() {
        service.foo();
    }
}
复制代码


结果:


a89db19d5f6243a7bbf12da833d9537c~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


通过上面的示例可以发现Synchronized同步方法时间耗费过长。


3、使用同步代码块解决同块方法的问题


那么如何使用同步代码块解决同步方法的问题,代码如下:


public class Demo11 {
    public static void main(String[] args) throws InterruptedException {
        Demo11Service service = new Demo11Service();
        Thread t1 = new Demo11ThreadA(service);
        t1.setName("A");
        t1.start();
        Thread t2 = new Demo11ThreadB(service);
        t2.setName("B");
        t2.start();
        Thread.sleep(10000);
        long start = Demo11Utils.start1 > Demo11Utils.start2 ? Demo11Utils.start2 : Demo11Utils.start1;
        long end = Demo11Utils.end1 > Demo11Utils.end2 ? Demo11Utils.end1 : Demo11Utils.end2;
        System.out.println("耗时:" + (end - start) /1000 + "秒");
    }
}
class Demo11Utils{
    static long start1;
    static long start2;
    static long end1;
    static long end2;
}
class Demo11Service{
    /*synchronized*/ public void foo(){
        try {
            System.out.println(Thread.currentThread().getName() + "开始任务");
            Thread.sleep(3000);
            synchronized (this) {
                System.out.println(Thread.currentThread().getName() + "处理计算结果");
            }
            System.out.println(Thread.currentThread().getName() + "结束任务");
        }catch(InterruptedException e){
            e.printStackTrace();
        }
    }
}
class Demo11ThreadA extends Thread{
    private Demo11Service service;
    public Demo11ThreadA(Demo11Service service){
        this.service = service;
    }
    @Override
    public void run() {
        Demo11Utils.start1 = System.currentTimeMillis();
        service.foo();
        Demo11Utils.end1 = System.currentTimeMillis();
    }
}
class Demo11ThreadB extends Thread{
    private Demo11Service service;
    public Demo11ThreadB(Demo11Service service){
        this.service = service;
    }
    @Override
    public void run() {
        Demo11Utils.start2 = System.currentTimeMillis();
        service.foo();
        Demo11Utils.end2 = System.currentTimeMillis();
    }
}
复制代码


结果:


c67fd46be54c4a67906f8315a210a910~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


可见耗时明显缩短!


4、synchronized代码块间的同步


/**
 * synchronized代码块的同步
 */
public class Demo13 {
    public static void main(String[] args) throws InterruptedException {
        DemoService13 service13 = new DemoService13();
        Thread t1 = new Demo13Thread1(service13);
        t1.start();
        Thread.sleep(100);
        Thread t2 = new Demo13Thread2(service13);
        t2.start();
    }
}
//声明一个服务
class DemoService13{
    public void foo1(){
        //同步代码块
        synchronized (this){
            //睡眠2s
            try {
                System.out.println("foo1方法开始时间:"+System.currentTimeMillis());
                Thread.sleep(2000);
                System.out.println("foo1方法结束时间:"+System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    public void foo2(){
        synchronized (this){
            System.out.println("foo2方法开始时间: "+System.currentTimeMillis());
            System.out.println("foo2方法结束时间: "+System.currentTimeMillis());
        }
    }
}
//声明一个子线程
class Demo13Thread1 extends Thread{
    private DemoService13 service13;
    //构造方法
    public Demo13Thread1(DemoService13 service){
        this.service13 = service;
    }
    public void run(){
        service13.foo1();
    }
}
//再声明一个子线程
class Demo13Thread2 extends Thread{
    private DemoService13 service13;
    //构造方法
    public Demo13Thread2(DemoService13 service){
        this.service13 = service;
    }
    public void run(){
        service13.foo2();
    }
}
复制代码


结果:


534bea54003444fcbac4610e407d5ab1~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


使用同步synchronize(this)代码时需要注意,当一个线程访问object的一个synchronized(this)同步代码块时,其它线程对这个object的其它syncrhonized(this)同步的访问会被阻塞,说明synchronized使用的对象锁是同一个。


synchroinze(this)代码块锁定的是当前对象。比如:


/**
 *synchroinze(this)代码块是锁定当前对象
 */
public class Demo14 {
    public static void main(String[] args) throws InterruptedException {
        Demo14Service service = new Demo14Service();
        Thread t1 = new Demo14ThreadA(service);
        Thread t2 = new Demo14ThreadB(service);
        t2.start();
        Thread.sleep(10);
        t1.start();
    }
}
class Demo14Service{
    synchronized public void foo1(){
        System.out.println("foo1方法正在运行");
    }
    public void foo2(){
        try {
            synchronized (this) {
                System.out.println("foo2方法开始");
                Thread.sleep(2000);
                System.out.println("foo2方法结束");
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}
class Demo14ThreadA extends Thread{
    private Demo14Service service;
    public Demo14ThreadA(Demo14Service service){
        this.service = service;
    }
    @Override
    public void run() {
        service.foo1();
    }
}
class Demo14ThreadB extends Thread{
    private Demo14Service service;
    public Demo14ThreadB(Demo14Service service){
        this.service = service;
    }
    @Override
    public void run() {
        service.foo2();
    }
}
复制代码


结果:


b110d7e6d68148668c3ff8aac0c9447e~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


synchronized(this)代码块与synchronized方法一样,synchronized(this)代码块也是锁定当前对象的。


5、使用任意对象作为对象锁


除了可以使用syncrhonized(this)来同步代码块,java还支持任意对象作为对象锁来实现同步的功能。这个任意对象就是成员变量或者方法中的参数,语法格式为:


synchronized(lockobj)
复制代码


在多个线程持有的对象锁为同一个对象的情况下,同一时间只有一个线程可以执行synchoronized(lockobj)同步代码块中的代码。如果使用的不是同一个对象锁,运行的结果就是异步调用,交叉输出结果。


比如:


/**
 * 使用任意对象作为对象锁
 */
public class Demo15 {
    public static void main(String[] args) {
        Demo15Service service = new Demo15Service();
        Thread t1 = new Demo15Thread(service);
        t1.setName("线程1");
        t1.start();
        Thread t2 = new Demo15Thread(service);
        t2.setName("线程2");
        t2.start();
    }
}
class Demo15Service{
    //锁对象
    private Object lockobject = new Object();
    public void foo(){
        //synchronized锁定对象
        synchronized (lockobject){
            try {
                System.out.println(Thread.currentThread().getName() + "开始于" + System.currentTimeMillis());
                Thread.sleep(2000);
                System.out.println(Thread.currentThread().getName() + "结束于" + System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class Demo15Thread extends Thread{
    private Demo15Service service;
    public Demo15Thread(Demo15Service service){
        this.service = service;
    }
    @Override
    public void run() {
        service.foo();
    }
}
复制代码


结果:


4c3d774b51b34387bd55d6c4d0f54f71~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


与synchronized (this)相比非tihs对象具有一定的优点。


一个类有很多个synchrnoized方法,虽然可以实现同步,但是会受到阻塞,影响运行效率。如果使用同步代码块非this对象,则synchronized非this对象的代码块中的程序与同步方法是不与其它的锁(this)争抢this锁,大大提高运行的效率。


/**
 * 非this对象具有的优点
 */
public class Demo16 {
    public static void main(String[] args) throws InterruptedException {
        Demo16Service service = new Demo16Service();
        Thread t1 = new Demo16ThreadA(service);
        t1.start();
        Thread.sleep(10);
        Thread t2 = new Demo16ThreadB(service);
        t2.start();
    }
}
class Demo16Service{
    private Object lockObject = new Object();
    public void foo(){
        try {
            synchronized (lockObject) {
                System.out.println("foo方法开始时间" + System.currentTimeMillis());
                Thread.sleep(2000);
                System.out.println("foot方法结束时间" + System.currentTimeMillis());
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
    synchronized public void foo2(){
        System.out.println("foo2方法开始时间" + System.currentTimeMillis());
        System.out.println("foo2方法结束时间" + System.currentTimeMillis());
    }
}
class Demo16ThreadA extends Thread{
    private Demo16Service service;
    public Demo16ThreadA(Demo16Service service){
        this.service  =service;
    }
    @Override
    public void run() {
        service.foo();
    }
}
class Demo16ThreadB extends Thread{
    private Demo16Service service;
    public Demo16ThreadB(Demo16Service service){
        this.service = service;
    }
    @Override
    public void run() {
        service.foo2();
    }
}
复制代码


结果:


1b17fe741b664d3788cde7f8979fc99f~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


5、synchronized(非this对象)解决脏读


import java.util.ArrayList;
import java.util.List;
public class Demo17 {
    public static void main(String[] args) throws InterruptedException {
        Demo17List list = new Demo17List();
        Thread t1 = new Demo17ThreadA(list);
        t1.start();
        Thread t2 = new Demo17ThreadB(list);
        t2.start();
        Thread.sleep(5000);
        System.out.println("list size is " + list.size());
    }
}
class Demo17List{
    private List list = new ArrayList();
    synchronized public void add(Object obj){
        list.add(obj);
    }
    synchronized public int size(){
        return list.size();
    }
}
class Demo17Service{
    private Object lockObject = new Object();
    public void add(Demo17List list, Object obj){
        try {
            synchronized (list) {
                if (list.size() < 1) {
                    Thread.sleep(2000);
                    list.add(obj);
                }
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}
class Demo17ThreadA extends Thread{
    private Demo17List list;
    public Demo17ThreadA(Demo17List list){
        this.list = list;
    }
    @Override
    public void run() {
        Demo17Service service = new Demo17Service();
        service.add(list, "a");
    }
}
class Demo17ThreadB extends Thread{
    private Demo17List list;
    public Demo17ThreadB(Demo17List list){
        this.list = list;
    }
    @Override
    public void run() {
        Demo17Service service = new Demo17Service();
        service.add(list, "b");
    }
}
复制代码


结果:


8781dbde3a924aacb2aea4de9a951067~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


对于synchronized(lockobj)格式的写法是将lockobj本身作为对象锁,总结上面的结果这样得出以下的结论:


a. 当多个线程同时执行syncrhonized(lockobj)同步代码块时结果是同步效果;


b. 当其它线程执行lockobj对象中的synchronized同步方法时也是同步效果;


c. 当其它线程执行lockobj对象方法里的synchronize(this)代码块时也是同步效果


如果其它线程调用不加synchronized关键字的方法时,还是异步调用。


6、半异步半同步


在并发模式中的同步和异步与IO模型中的同步和异步是完全不同的概念。


在IO模型中,同步和异步区分的是内核向应用程序通知的是何种IO事件(是就绪事件还是完成事件),以及该由谁来完成IO读写(是应用程序还是内核)。


而在并发模式中的同步指的是程序完全按照代码序列的顺序执行,异步指的是程序的执行需要由系统事件来驱动。常见的系统事件包括中断信号等。


按照同步方式运行的线程称为同步线程,按照异步方式运行的线程成为异步线程。显然异步线程的执行效率高,实时性强,这是很多嵌入式程序采用的模型。但编写异步方式执行的程序相对复杂,难于调试和扩展,且不适合大量的并发。而同步线程则相反,它虽然效率比较低,实时性较差,但逻辑简单。因此,对于某些既要求较好的实时性,又要求同时处理多个客户请求的应用程序,就可以同时使用同步线程和异步线程来实现。即使用半同步/半异步模式来实现!


如果使用synchronized关键字来实现半同步/半异步代码如下:


/**
 * 半同步和半异步
 */
public class Demo12 {
    public static void main(String[] args) {
        Demo12Service service = new Demo12Service();
        Thread t1 = new Demo12Thread(service);
        t1.setName("A");
        t1.start();
        Thread t2 = new Demo12Thread(service);
        t2.setName("B");
        t2.start();
    }
}
class Demo12Service {
    public void foo(){
        try{
            for (int i = 0; i < 100; i++) {
                System.out.println("非同步线程" + Thread.currentThread().getName() + ", i=" + i);
                Thread.sleep(10);
            }
            System.out.println();
            synchronized (this){
                for (int i = 0; i < 100; i++) {
                    System.out.println("同步线程" + Thread.currentThread().getName() + ", i=" + i);
                    Thread.sleep(10);
                }
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}
class Demo12Thread extends Thread{
    private Demo12Service service;
    public Demo12Thread(Demo12Service service){
        this.service = service;
    }
    @Override
    public void run() {
        service.foo();
    }
}
复制代码


结果:


21c3a5ef074648fd8142bd6e13f8434b~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


不在synchronized块中的就是异步执行,在synchroinzed块中的代码就是同步执行。


非同步的输出是交叉的,而同步线程只有线程a执行完了才执行线程B。


7、synchronized同步静态方法与synchronized(class)代码块


前面讲了synchronized关键字修饰方法,但是并没有讲修饰静态方法,关键字synchronized还可以修饰静态方法,


synchronized修饰静态方法就是对象当前的*.java文件对应的Class进行加锁。比如:


public class Demo18 {
    public static void main(String[] args) {
        Thread t1 = new Demo18ThreadA();
        t1.setName("A");
        t1.start();
        Thread t2 = new Demo18ThreadB();
        t2.setName("B");
        t2.start();
    }
}
class Demo18Service{
    synchronized public static void foo1(){
        System.out.println(Thread.currentThread().getName() + "进入方法foo1在" + System.currentTimeMillis());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "结束方法foo1在" + System.currentTimeMillis());
    }
    synchronized public static void foo2(){
        System.out.println(Thread.currentThread().getName() + "进入方法foo2在" + System.currentTimeMillis());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "结束方法foo2在" + System.currentTimeMillis());
    }
}
class Demo18ThreadA extends Thread{
    @Override
    public void run() {
        Demo18Service.foo1();
    }
}
class Demo18ThreadB extends Thread{
    @Override
    public void run() {
        Demo18Service.foo2();
    }
}
复制代码


结果:


13d958f5e3e5447e83c0db1480a5e4f7~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


从上面的结果可以发现在静态方法上使用synchronized修饰与在非静态方法上使用的结果是一致的,都是同步运行。但是其实从本质来讲它们是有区别的,在静态方法上使用synchronized是给Class类上锁,而在非静态方法上使用syncrhonized是给对象上锁。


public class Demo19 {
    public static void main(String[] args) {
        Demo19Service service = new Demo19Service();
        Thread t1 = new Demo19ThreadA(service);
        t1.setName("A");
        t1.start();
        Thread t2 = new Demo19ThreadB(service);
        t2.setName("B");
        t2.start();
    }
}
class Demo19Service{
    synchronized public static void foo1(){
        System.out.println(Thread.currentThread().getName() + "进入foo1方法在" + System.currentTimeMillis());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "结束foo1方法在" + System.currentTimeMillis());
    }
    synchronized public void foo2(){
        System.out.println(Thread.currentThread().getName() + "进入foo2方法在" + System.currentTimeMillis());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "结束foo2方法在" + System.currentTimeMillis());
    }
}
class Demo19ThreadA extends Thread{
    private Demo19Service service;
    public Demo19ThreadA(Demo19Service service){
        this.service = service;
    }
    @Override
    public void run() {
        service.foo2();
    }
}
class Demo19ThreadB extends Thread{
    private Demo19Service service;
    public Demo19ThreadB(Demo19Service service){
        this.service = service;
    }
    @Override
    public void run() {
        service.foo1();
    }
}
复制代码


结果:


03b8d3e18fb94825a582add4d843c7d7~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


上面以异步方式运行的原因是因为持有锁是不一样的,非静态方法持有提对象锁,而静态方法持有的是Class锁,Class锁可以对类的所有对象实例起作用。


同步synchronized(class)代码块的作用其实和synchronized static方法的作用是一样的


public class Demo20 {
    public static void main(String[] args) {
        Demo20Service service = new Demo20Service();
        Thread t1 = new Demo20ThreadA(service);
        t1.setName("A");
        t1.start();
        Thread t2 = new Demo20ThreadA(service);
        t2.setName("B");
        t2.start();
    }
}
class Demo20Service{
    synchronized public static void foo1(){
        System.out.println(Thread.currentThread().getName() + "进入foo1方法在" + System.currentTimeMillis());
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName() + "结束foo1方法在" + System.currentTimeMillis());
    }
    public static void foo2(){
        synchronized (Demo20Service.class) {
            System.out.println(Thread.currentThread().getName() + "进入foo1方法在" + System.currentTimeMillis());
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "结束foo1方法在" + System.currentTimeMillis());
        }
    }
}
class Demo20ThreadA extends Thread{
    private Demo20Service service;
    public Demo20ThreadA(Demo20Service service){
        this.service = service;
    }
    @Override
    public void run() {
        service.foo1();
    }
}
class Demo20ThreadB extends Thread{
    private Demo20Service service;
    public Demo20ThreadB(Demo20Service service){
        this.service = service;
    }
    @Override
    public void run() {
        service.foo2();
    }
}
复制代码


结果:


60bb9e0ec3f04f5a97884f6390aabf98~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


8、synchronized(String)*


当使用synchronized关键字将String作为锁对象时:


public class Demo21 {
    public static void main(String[] args) {
        Thread t1 = new Demo21ThreadA();
        t1.setName("A");
        t1.start();
        Thread t2 = new Demo21ThreadB();
        t2.setName("B");
        t2.start();
    }
}
class Demo21Service{
    public static void foo1(String lockObject){
        try {
            synchronized (lockObject) {
                while (true) {
                    System.out.println("线程" + Thread.currentThread().getName());
                    Thread.sleep(1000);
                }
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
    public static void foo2(Object lockObject){
        try {
            synchronized (lockObject) {
                while (true) {
                    System.out.println("线程" + Thread.currentThread().getName());
                    Thread.sleep(1000);
                }
            }
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}
class Demo21ThreadA extends Thread{
    @Override
    public void run() {
        Demo21Service.foo1("AA");
    }
}
class Demo21ThreadB extends Thread{
    @Override
    public void run() {
        Demo21Service.foo2("AA");
    }
}
复制代码


结果:


dca5eac83908416894950c9f0b63852b~tplv-k3u1fbpfcp-zoom-in-crop-mark_1304_0_0_0.webp.jpg


通过上面结果可以发现只会打印线程B。只有线程B在运行的原因是,两个线程的对象锁都是使用AA,两个线程持有的相同的锁,所以造成线程B能运行。这就是String常量所带来的问题。所以不应该使用字符串类型作为对象锁,而应该使用其它类型,例如new Object(),对象就不会放入缓存 。


3 总结


多线程编程之线程的同步机制(上): Synchronized同步方法和本篇文章主要讲了在多线程编程中


Synchronized关键字对于同步机制的作用。Synchronized关键字不仅仅能够修饰方法还能够修饰代码块。

目录
相关文章
|
2月前
|
安全 Java Kotlin
Java多线程——synchronized、volatile 保障可见性
Java多线程中,`synchronized` 和 `volatile` 关键字用于保障可见性。`synchronized` 保证原子性、可见性和有序性,通过锁机制确保线程安全;`volatile` 仅保证可见性和有序性,不保证原子性。代码示例展示了如何使用 `synchronized` 和 `volatile` 解决主线程无法感知子线程修改共享变量的问题。总结:`volatile` 确保不同线程对共享变量操作的可见性,使一个线程修改后,其他线程能立即看到最新值。
|
2月前
|
安全 Java 编译器
深入理解Java中synchronized三种使用方式:助您写出线程安全的代码
`synchronized` 是 Java 中的关键字,用于实现线程同步,确保多个线程互斥访问共享资源。它通过内置的监视器锁机制,防止多个线程同时执行被 `synchronized` 修饰的方法或代码块。`synchronized` 可以修饰非静态方法、静态方法和代码块,分别锁定实例对象、类对象或指定的对象。其底层原理基于 JVM 的指令和对象的监视器,JDK 1.6 后引入了偏向锁、轻量级锁等优化措施,提高了性能。
81 3
|
3月前
|
Java 调度
Java 线程同步的四种方式,最全详解,建议收藏!
本文详细解析了Java线程同步的四种方式:synchronized关键字、ReentrantLock、原子变量和ThreadLocal,通过实例代码和对比分析,帮助你深入理解线程同步机制。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
Java 线程同步的四种方式,最全详解,建议收藏!
|
3月前
|
Java 开发者
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
在Java多线程编程的世界里,Lock接口正逐渐成为高手们的首选,取代了传统的synchronized关键字
67 4
|
4月前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
71 3
|
4月前
|
Java 开发者
在Java多线程编程中,选择合适的线程创建方法至关重要
【10月更文挑战第20天】在Java多线程编程中,选择合适的线程创建方法至关重要。本文通过案例分析,探讨了继承Thread类和实现Runnable接口两种方法的优缺点及适用场景,帮助开发者做出明智的选择。
47 2
|
4月前
|
Java
Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口
【10月更文挑战第20天】《JAVA多线程深度解析:线程的创建之路》介绍了Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口。文章详细讲解了每种方式的实现方法、优缺点及适用场景,帮助读者更好地理解和掌握多线程编程技术,为复杂任务的高效处理奠定基础。
75 2
|
4月前
|
安全 Java 开发者
Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用
本文深入解析了Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用。通过示例代码展示了如何正确使用这些方法,并分享了最佳实践,帮助开发者避免常见陷阱,提高多线程程序的稳定性和效率。
91 1
|
17天前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
本文详细介绍了如何在Linux中通过在业务线程中注册和处理信号。我们讨论了信号的基本概念,并通过完整的代码示例展示了在业务线程中注册和处理信号的方法。通过正确地使用信号处理机制,可以提高程序的健壮性和响应能力。希望本文能帮助您更好地理解和应用Linux信号处理,提高开发效率和代码质量。
42 17
|
26天前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
通过本文,您可以了解如何在业务线程中注册和处理Linux信号。正确处理信号可以提高程序的健壮性和稳定性。希望这些内容能帮助您更好地理解和应用Linux信号处理机制。
54 26