多线程与高并发基础(基础篇二)

本文探讨了多线程环境下使用synchronized关键字解决竞态条件的方法。通过对比加锁前后对计数器进行递增操作的结果,展示了synchronized如何确保线程安全。此外,还介绍了synchronized的不同应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

synchronized关键字

一、什么时候程序需要锁?
多个线程同时访问某段代码或者某个临界资源进行修改操作时,需要加锁
二、程序为什么需要锁?
eg. 线程A和线程B同时对数字n(默认0)做++操作,
1、线程A读取到数字n为0时,去做++(非原子性)操作,
2、同时线程B读取到数字n为0时,也去做++操作
3、做了两次++操作,最终结果还是1(正确应该是2)。

/**
 * @Auther wangdongdong
 * @Date 2021/7/21 0021 下午 21:14
 * @Description 两个线程同时对数字n=0做1万次++操作
 * @Verson 1.0
 */
public class TestNuumPlusBySync {
    public class TestNuumPlusBySync implements Runnable{
    static TestNuumPlusBySync instance=new TestNuumPlusBySync();
    static volatile int n=0;volatile只能保证线程可见性,不能保证线程安全


    //加不加synchronized执行结果完全不同
    public /*synchronized*/ static void increase(){
        n++;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100000; i++) {
            increase();
        }
    }

    public static void main(String[] args) throws Exception{
        Thread t1=new Thread(instance);
        Thread t2=new Thread(instance);
        t1.start();t2.start();
        t1.join();t2.join();
        System.out.println(n);
    }
}

不加synchronized执行结果:
197771synchronized执行结果:
200000

三、如何使用synchronized?
1、指定加锁对象
2、直接作用于实例方法
3、直接作用于静态方法

//synchronized的几种用法
public class Test_Synchronized {
    /*
     * 1、指定加锁对象
     * 2、直接作用于实例方法
     * 3、直接作用于静态方法
     */

    private int count =10;
    
    //防止对象印用发生变化,最好对象定义为final
    private final Object o=new Object();

    //1、指定加锁对象
    public void m1(){
        synchronized (o){
            count--;
            System.out.println(Thread.currentThread().getName()+" count="+count);
        }
    }

    //2、直接作用于实例方法
    public void m2(){
        synchronized (this){ //用this锁定当前对象
            count--;
            System.out.println(Thread.currentThread().getName()+" count="+count);
        }
    }
    
    public synchronized void m3(){ //等同于方法2
        count--;
        System.out.println(Thread.currentThread().getName()+" count="+count);
    }
}

//3、直接作用于静态方法
class test_static{
    private static int count=20;
    
    public synchronized static void m(){
        count--;
        System.out.println(Thread.currentThread().getName()+" count="+count);
    }
    
    //静态方法没有this对象,方法上使用synchronized,相当于synchronized(T.class)
    public  static void m_1(){
        synchronized(test_static.class){
            count--;
            System.out.println(Thread.currentThread().getName()+" count="+count); 
        }
    }
}

使用了synchronized就没必要使用volatile,因为synchronized既保证了原子性,也保证了一致性
synchronized遇到异常未处理,默认情况会释放锁,可能导致数据不一致

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值