Android多线程 线程同步学习

本文详细探讨了Android开发中线程同步的重要性,包括竞态条件和内存可见性问题,介绍了synchronized关键字、同步代码块、重入锁和条件对象。此外,文章还讨论了volatile关键字的作用,如保证可见性和有序性,但不保证原子性,并举例说明了使用volatile的正确条件。
摘要由CSDN通过智能技术生成

线程同步

为什么引入同步机制?

多线程因为存在共享资源,为了保证其原子性,保证线程安全,必须引入同步机制。

一、必要的概念

因为多线程的共享内存,当多线程对共享内存进行操作的时候,就存在两个大问题必须解决:竞态条件、内存可见性

1、竞态条件

当多线程访问和操作同一对象的时候,如果对资源访问的访问顺序敏感,就称存在竞态条件。

例子:

比如线程A、B都从内存拿数据count,A对数据+2,B对数据+3,所以按照我们期待的结果最终写入内存的数据应该是5。但是其实不是这样的,因为当初A、B从内存拿数据count的时候,数据count是0,所以最终count的结果取决于A、B谁后写入内存谁后写入,count就是对应的执行结果。

常用的解决方法:

  • 使用synchronized关键字
  • 使用显式锁(Lock)
  • 使用原子变量
2、内存可见性

关于内存可见性的问题首先要从内存和cpu的配合谈起,内存是一个硬件,执行速度比CPU慢几百倍,所以在计算机中,CPU执行运算的时候,不会每次运算都和内存进行数据交互,而是先把一些数据写入CPU中的缓存区(寄存器和各级缓存),在结束以后再写入内存。这个过程是极其快的,单线程下是没有任何问题的。

但是多线程就出现了问题,一个线程对内存中的一个数据做出了修改,但是并没有及时写入内存(暂时放在缓存中);这时候另一个线程对同样的数据进行修改的时候拿到的就是内存中还没有被修改的数据,也就是说一个线程对一个共享变量的修改,另一个线程不能马上看到,甚至永远看不到。就跟上面的例子也是一样的,不过竞态条件关注的是因为执行顺序而带来的结果的不同,而内存可见性强调的是数据的原子性。

这就是内存可见性问题。

常用的解决方法:

  • 使用volatile关键字
  • 使用synchronized关键字
  • 使用显式锁同步

二、线程同步

synchronized 方法(同步方法)

从java 1.0 版开始,Java中的每个对象都有一个内部锁。如果一个方法用synchronized关键字声明,那么对象的锁将保护整个方法。也就说,要调用该方法,线程必须获得内部的对象锁。避免了程序员使用显式锁的方式lock和unlock。

代码如下:

public class synchronizedTest {
    private  int money = 100;
    public  synchronized int getMoney(int number){
        if(number < 0){
            return -1;
        }else if(number > money){
            return -2;
        }else if(money < 0){
            return -3;
        }else{
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        money -= number;
        System.out.println("存款剩余" + money);
        return number;
    } 
}

等价于

public class synchronizedTest {
    Lock mLock = new ReentrantLock();
    private  int money = 100;
    public int getMoney(int number){
        mLock.lock();
        try{
            if(number < 0){
                return -1;
            }else if(number > money){
                return -2;
            }else if(money < 0){
                return -3;
            }else{
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值