Java--线程安全、synchronized用法

本文讨论了多线程编程中如何确保线程安全,通过分析示例展示了不加锁的并发操作可能导致数据不一致,然后介绍了如何使用synchronized关键字实现代码的原子性和锁定机制,以保证在并发环境下的正确性。

知识点清单

原子性

提供互斥访问,同一时刻只能有一个线程对数据进行操作

原子操作不能被中断的一个或一系列操作具有原子性
临界区是指锁和解锁之间的代码块,任何时候临界区最多只有一个线程能执行
synchronized(同步锁)代码块在任意时刻最多只有一个线程能执行

 线程安全

多线程并发同时对共享数据进行读写会造成混乱,也就是线程不安全。

示例如下:

package src.com.threadcase04;

import src.com.threadcase02.MyRun;

public class Demo {

    public static void main(String[] args) throws Exception{

        MyRun1 mr = new MyRun1();

        Thread t1 = new Thread(mr);
        Thread t2 = new Thread(mr);

        t1.start();
        t2.start();
        t1.join();
        t2.join();

        System.out.println("sum = "+Sum.sum);
    }

}
 class Sum {
    public static int sum = 2000000;
}

package src.com.threadcase04;

public class MyRun1 implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 1000000; i++) {
            Sum.sum --;
            //System.out.println(Sum.sum);
        }
    }
}

 

        如上,有两个线程进行sum--,由于线程的并发性,使得线程1在操作的过程中,线程2抢了线程1进行了操作,导致两个线程同时对一个sum进行了减一。是的最终结果sum不为零;

        当在线程里面加入System.out.println(Sum.sum)代码,运行结果就会是0,原因是println方法里面自带了synchronized锁。

        上面这种情况就是线程不安全,在线程1运行时,线程2插入进来了,为了让线程安全,就要保证线程内部操作的原子性

实现代码的原子性,就要对代码进行加锁解锁。

synchronized(lock){
    Sum.sum ++;
}

修改如下

package src.com.threadcase04;

import src.com.threadcase02.MyRun;

public class Demo {

    public static void main(String[] args) throws Exception{

        MyRun1 mr = new MyRun1();

        Thread t1 = new Thread(mr);
        Thread t2 = new Thread(mr);

        t1.start();
        t2.start();
        t1.join();
        t2.join();

        System.out.println("sum = "+Sum.sum);
    }

}
 class Sum {
    public static Object lock = new Object(); final只读,用于当作共享实例-锁
    public static int sum = 2000000;
}
package src.com.threadcase04;

import java.util.concurrent.BlockingDeque;
import java.util.concurrent.BlockingQueue;

public class MyRun1 implements Runnable{
    @Override
    public void  run() {
        for (int i = 0; i < 1000000; i++) {
                synchronized (Sum.lock){
                    Sum.sum --;
                }
            // System.out.println(Sum.sum);
        }
    }
}

此时运行结果为0;

synchronized的用法:找出共享线程代码块,选择一个共享实例作为锁,使用synchronized(Lockobj){...};

Lockobj可以选择一个共享实例,例如定义一个 public static final Object lock = new Object(),使用synchronized(lock){...};;

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

幼儿园大哥7

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值