synchronized同步锁如何保证三大特性

本文详细探讨了Java中的synchronized关键字,包括其如何保证原子性、可见性和防止重排序,以及可重入锁的概念和重要性。通过示例代码解释了synchronized如何确保在同一时刻只有一个线程执行,防止并发安全问题,并防止死锁的发生。同时,文章还展示了可重入锁的使用场景,说明了其在提升代码封装性和避免死锁方面的优势。
摘要由CSDN通过智能技术生成

synchronized如何保证三大特性

保证在同一时刻最多只有一个线程执行,以达到保证并发安全的效果
synchronized(锁对象){
    //受保护的资源
}
 

synchronized保护原子性的原理

synchronized保证原子性的原理,synchronized保证只有一个线程拿到锁,能够进入同步代码块;

synchronized解决可见性

执行synchronized时,会对应lock原子操作会刷新工作内存中共享变量的值

synchronized解决重排序

package com.synconized;
import java.util.HashSet;

public class Demo4 {
    static int x;
    static int y;
    static int a;
    static int b;
    static Object obj = new Object();
    public static void main(String[] args) throws InterruptedException {
        HashSet<String> result= new HashSet<>();
        while (true){
            x =0;
            y =0;
            a =0;
            b =0;
            //线程1
            Thread t1 = new Thread(()->{
                synchronized (obj) {  
                    a = y;  // a = 0
                    x = 1;
                }
            });
            //线程2
            Thread t2 = new Thread(()->{
                synchronized (obj) {  

                    b = x;  //b = 0
                    y = 1;
                }
            });
            t1.start();
            t2.start();
            t2.join();
            t1.join();
            result.add("[a="+a + ",b=" + b+"]");
            System.out.println(result);
            /*
           多跑一会结果出现的情况:
           [a=0,b=0, a=1,b=0, a=0,b=1, a=1,b=1]
            先运行t1线程结果就是:a=0,b=1
            先运行t2线程结果就是:a=1,b=0
            其他两种结果是顺序重排了
             */
        }
    }
}

锁的原理,同一时间只允许同步块中有一个线程执行

synchronized的可重入特性

1 什么是可重入(递归锁):

        指的是同一线程的外层函数获得锁之后,内层函数可以直接再次获取该锁。类车牌照摇号,可重入就是拿到之后就可以再次用起来,可以一直摇号,如果还需要重新竞争的话就叫不可重入锁
synchronized的锁对象中有一个计数器(recursions变量)会记录线程获得几次锁,在执行完同步代码块时,计数器的数量会-1,直到计数器的数量为0,就释放这个锁

2 可重入有什么好处:

            避免死锁:如果不可重入就会一直等待锁,很容易造成死锁
            提升封装性:同步代码块可以调用另一个同步代码块,方便通过方法封装

package com.synconized;

import java.util.concurrent.TimeUnit;

public class Demo5 {
    public static void main(String[] args) {
        new MyThread().start();
        new MyThread().start();
    }
}
class MyThread extends Thread{
    public MyThread() {
        System.out.println(getName()+"启动了");
    }

    @Override
    public void run() {
        synchronized (MyThread.class){
            //获取到锁,计数器+1
            System.out.println(getName()+"获取到锁,进入同步代码块1开始运行");
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (MyThread.class){
                // 再次获取到锁,计数器+1
                System.out.println(getName()+"获取到锁,进入同步代码块2开始运行");
                try {
                    TimeUnit.SECONDS.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        }
    }
}

一个线程获取到锁则执行逻辑,另外一个获取不到锁的线程就会进入等待,直到前面线程把锁释放

如果锁一直没有释放,那么其他需要锁的线程将无法执行,线程死锁。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值