关于线程安全的认识

一、线程安全

1.什么是线程安全?

当多个线程访问某一类(对象或方法)时,这个类(对象或方法)始终表现出正确的行为,则该类(对象或方法)就是线程安全的,当线程同步时即保证了线程安全。多线程访问时,采用加锁机制,当一个线程访问该类的数据时,进行保护,其他进程不能进行访问直到该线程读取完防止数据不一致或者数据污染。

2.线程安全的起因

线程安全由全局变量和静态变量引起,若线程对全局变量和静态变量只有读操作,而无写操作,则线程安全;相反,若多个线程对数据进行更改,则导致数据不一致,影响线程安全。

3.线程不安全

线程不安全:与线程安全对立,即不提供数据保护,可能会出现多个线程先后更改数据造成所得到的数据是脏数据。

二、线程安全的三大特性

1.原子性

指在一个操作中,cpu不可以在中途暂停再调度,既不被中断操作,要不执行完成,要么不执行。如果一个操作是原子性的,那么线程并发情况下,不会出现变量被修改的情况。

2.可见性

即线程之间的可见性,当一个线程修改线程共享中的变量时,别的线程能立马得知这个修改。

3.有序性

指程序在执行时,程序的执行代码顺序与语句顺序一致。

三、synchronized、Lock、volatile

1.synchronized

(1)synchronize是java语言的关键字,其作用是:控制线程同步,实现互斥,保证在多线程环境下,不被多个线程同时执行,确保数据的完整性。
(2)从程序性能角度上考虑:在使用synchronized关键字时,要尽量减小它的使用范围,减少资源浪费。
(3)可能出现的问题:多线程访问时,使用synchronized关键字后,得到锁的线程可以执行synchronized里的代码,得不到的线程会不断去尝试去获得锁,直到获得锁,因此会出现锁竞争的问题。
(4)在操作系统中多个线程可以共享系统中的各种资源,但其中许多资源只能一次只能为一个进程所使用,因此将一次仅允许一个进程使用的资源称为临界资源,而在进程中,访问临界资源的那段代码称为临界区,使用synchronized关键字的代码块可以称之为临界区。

2.Lock

(1)Lock是接口,通过接口的实现类可以实现同步。
(2)通过Lock可以解决synchronized的锁竞争问题,让等待锁的线程响应中断,不会让等待的线程无期限地等待下去。
(3)通过Lock可以知道锁有没有成功被获取
(4)与synchronized的不同,Lock需要手动去释放锁,否则会导致死锁现象。synchronized可以加在方法上,也可以加在特定的代码块中,括号中表示需要锁的对象,而Lock需要显示指定起始位置与终止位置。

3.volatile

(1)volatile是一个类型修饰符,其作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值。
(2)volatile关键字强制从公共堆栈中取得变量的值,而不是线程私有的数据栈中取得变量。
(3)volatile的两大特性:
1.禁止指令的重排序优化
防止虚拟机为了降低内存操作速度远慢于CPU运行速度所带来的CPU空置的影响,而按照自己的一些规则将程序编写顺序打乱。
2.提供内存可见性(变量在多个线程之间可见)。

四、总结

1.在 Java 中 volatile、synchronized实现可见性。
2.synchronized 和在 lock、unlock 中操作保证原子性。
3.Java 语言提供了 volatile 和 synchronized 两个关键字来保证线程之间操作的有序性,volatile 是因为其本身包含“禁止指令重排序”的语义,synchronized 是由“一个变量在同一个时刻只允许一条线程对其进行 lock 操作”这条规则获得的,此规则决定了持有同一个对象锁的两个同步块只能串行执行。

你可能感兴趣的:(多线程,个人总结)