synchronized
- synchronized关键字:表示“同步”的。它可以对“多行代码”进行“同步”——将多行代码当成是一个完整的整体,一个线程如果进入到这个代码块中,会全部执行完毕,执行结束后,其它线程才会执行。这样可以保证这多行的代码作为完整的整体,被一个线程完整的执行完毕。
- synchronized被称为“重量级的锁”方式,也是“悲观锁”——效率比较低。
- synchronized有几种使用方式:
- 同步代码块
- 同步方法【常用】
当我们使用多个线程访问同一资源的时候,且多个线程中对资源有写的操作,就容易出现线程安全问题。
下面文章提供代码,用以参考学习。 线程卖票问题
要解决上述多线程并发访问一个资源的安全性问题:也就是解决重复票与不存在票问题,Java中提供了同步机制(synchronized)来解决。
同步代码块
synchronized(同步锁){
需要同步操作的代码
}
同步锁: 对象的同步锁只是一个概念,可以想象为在对象上标记了一个锁.
- 锁对象 可以是任意类型。
- 多个线程对象 要使用同一把锁。
注意:在任何时候,最多允许一个线程拥有同步锁,谁拿到锁就进入代码块,其他的线程只能在外等着(BLOCKED)。
同步方法
同步方法:使用synchronized修饰的方法,就叫做同步方法,保证A线程执行该方法的时候,其他线程只能在方法外等着。
public synchronized void method(){
可能会产生线程安全问题的代码
}
同步锁是谁? 对于非static方法,同步锁就是this。 对于static方法,我们使用当前方法所在类的字节码对象(类名.class)。
Lock锁
java.util.concurrent.locks.Lock机制提供了比synchronized代码块和synchronized方法更广泛的锁定操作,同步代码块/同步方法具有的功能Lock都有,除此之外更强大 Lock锁也称同步锁,加锁与释放锁方法化了,如下:
public void lock() :加同步锁。public void unlock() :释放同步锁。 先创建Lock对象
Lock lock = new ReentrantLock();
再在需要同步的代码段前后加上
lock.lock();
需要同步操作的代码
lock.unlock();
注: 最好将lock.unlock();放到finally中防止发生异常跳过
多线程的安全性问题-可见性
概述: 一个线程没有看见另一个线程对共享变量的修改 为什么没有看见: 简而言之: 就是所有共享变量都是存在主内存中的,线程在执行的时候,有单独的工作内存,会把共享变量拷贝一份到线程的单独工作内存中,并且对变量所有的操作,都是在单独的工作内存中完成的,不会直接读写主内存中的变量值
多线程的安全性问题-有序性
有些时候“编译器”在编译代码时,会对代码进行“重排”
多线程的安全性问题-原子性
概述:所谓的原子性是指在一次操作或者多次操作中,要么所有的操作全部都得到了执行并且不会受到任何因素的干扰而中断,要么所有的操作都不执行,多个操作是一个不可以分割的整体。
线程安全的介绍,下门的文章可能会对你有帮助。 多线程之原子性,可见性,有序性,并发问题解决
|