线程同步、线程安全的实现方式

为什么要同步?

     因为当我们有多个线程要同时访问一个变量或对象时,如果这些线程中既有读又有写操作时,就会导致变量值或对象的状态出现混乱,从而导致程序异常。举个例子,如果一个银行账户同时被两个线程操作,一个取100块,一个存钱100块。假设账户原本有0块,如果取钱线程和存钱线程同时发生,会出现什么结果呢?1.取钱不成功,账户余额是1002.取钱成功了,账户余额是0;那到底是哪个呢?很难说清楚。因此多线程同步就是要解决这个问题。

第一种把修改数据的方法上加synchronized:

1)即有synchronized关键字修饰的方法。 由于java的每个对象都有一个内置锁,当用此关键字修饰方法时,内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。

第二种代码块锁:

2)同步代码块,即有synchronized关键字修饰的语句块。被该关键字修饰的语句块会自动被加上内置锁,从而实现同步。

第三种使用ReentrantLock()对象跟synchronized作用一样:

4)双重锁 ReentrantLock,和synchronized方法和代码块具有相同的意思

//需要声明这个锁 

    private Lock lock = new ReentrantLock(); 

// 存钱 

    public void addMoney(int money) { 

        lock.lock();//上锁 

        try

        count += money; 

        System.out.println(System.currentTimeMillis() + "存进:" + money); 

        }finally

            lock.unlock();//解锁 

        } 

    } 

第四种在要修改的变量上加volatile这个变量就受保护了,就是线程安全的:

4)使用特殊域变量(volatile)实现线程同步,在公共的变量上用volatile修饰

1volatile关键字为域变量的访问提供了一种免锁机制;

2)使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新;

3)因此每次使用该域就要重新计算,而不是使用寄存器中的值;

4volatile不会提供任何原子操作,它也不能用来修饰final类型的变量。

猜你喜欢

转载自blog.csdn.net/qq_43154385/article/details/87855744