JAVA线程锁及部分特性
来源:互联网 发布:sql cast函数有什么用 编辑:程序博客网 时间:2024/06/07 01:59
锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchronized 和 ReentrantLock等等 ) 。
一、分类
1、自旋锁
2、自旋锁的其他种类
3、阻塞锁
4、可重入锁
5、读写锁
6、互斥锁
7、悲观锁
8、乐观锁
9、公平锁
10、非公平锁
11、偏向锁
12、对象锁
13、线程锁
14、锁粗化
15、轻量级锁
16、锁消除
17、锁膨胀
18、信号量
1、自旋锁
自旋锁是采用让当前线程不停地的在循环体内执行实现的,当循环的条件被其他线程改变时 才能进入临界区。如下
01
public
class
SpinLock {
02
03
private
AtomicReference<Thread> sign =
new
AtomicReference<>();
04
05
public
void
lock(){
06
Thread current = Thread.currentThread();
07
while
(!sign .compareAndSet(
null
, current)){
08
}
09
}
10
11
public
void
unlock (){
12
Thread current = Thread.currentThread();
13
sign .compareAndSet(current,
null
);
14
}
15
}
使用了CAS原子操作,lock函数将owner设置为当前线程,并且预测原来的值为空。unlock函数将owner设置为null,并且预测值为当前线程。
当有第二个线程调用lock操作时由于owner值不为空,导致循环一直被执行,直至第一个线程调用unlock函数将owner设置为null,第二个线程才能进入临界区。
由于自旋锁只是将当前线程不停地执行循环体,不进行线程状态的改变,所以响应速度更快。但当线程数不停增加时,性能下降明显,因为每个线程都需要执行,占用CPU时间。如果线程竞争不激烈,并且保持锁的时间段。适合使用自旋锁。
注:该例子为非公平锁,获得锁的先后顺序,不会按照进入lock的先后顺序进行。
阻塞锁,与自旋锁不同,改变了线程的运行状态。
在JAVA环境中,线程Thread有如下几个状态:
1,新建状态
2,就绪状态
3,运行状态
4,阻塞状态
5,死亡状态
2、阻塞锁
阻塞锁,可以说是让线程进入阻塞状态进行等待,当获得相应的信号(唤醒,时间) 时,才可以进入线程的准备就绪状态,准备就绪状态的所有线程,通过竞争,进入运行状态。
JAVA中,能够进入\退出、阻塞状态或包含阻塞锁的方法有 ,synchronized 关键字(其中的重量锁),ReentrantLock,Object.wait()\notify(),LockSupport.park()/unpart()(j.u.c经常使用)
下面是一个JAVA 阻塞锁实例
01
package
lock;
02
03
import
java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
04
import
java.util.concurrent.locks.LockSupport;
05
06
public
class
CLHLock1 {
07
public
static
class
CLHNode {
08
private
volatile
Thread isLocked;
09
}
10
11
@SuppressWarnings
(
"unused"
)
12
private
volatile
CLHNode tail;
13
private
static
final
ThreadLocal<CLHNode> LOCAL =
new
ThreadLocal<CLHNode>();
14
private
static
final
AtomicReferenceFieldUpdater<CLHLock1, CLHNode> UPDATER = AtomicReferenceFieldUpdater.newUpdater(CLHLock1.
class
,
15
CLHNode.
class
,
"tail"
);
16
17
public
void
lock() {
18
CLHNode node =
new
CLHNode();
19
LOCAL.set(node);
20
CLHNode preNode = UPDATER.getAndSet(
this
, node);
21
if
(preNode !=
null
) {
22
preNode.isLocked = Thread.currentThread();
23
LockSupport.park(
this
);
24
preNode =
null
;
25
LOCAL.set(node);
26
}
27
}
28
29
public
void
unlock() {
30
CLHNode node = LOCAL.get();
31
if
(!UPDATER.compareAndSet(
this
, node,
null
)) {
32
System.out.println(
"unlock\t"
+ node.isLocked.getName());
33
LockSupport.unpark(node.isLocked);
34
}
35
node =
null
;
36
}
37
}
在这里我们使用了LockSupport.unpark()的阻塞锁。 该例子是将CLH锁修改而成。
阻塞锁的优势在于,阻塞的线程不会占用cpu时间, 不会导致 CPu占用率过高,但进入时间以及恢复时间都要比自旋锁略慢。
在竞争激烈的情况下 阻塞锁的性能要明显高于 自旋锁。
理想的情况则是; 在线程竞争不激烈的情况下,使用自旋锁,竞争激烈的情况下使用,阻塞锁。
3、可重入锁
可重入锁,也叫做递归锁,指的是同一线程 外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。在JAVA环境下 ReentrantLock 和synchronized 都是 可重入锁
- JAVA线程锁及部分特性
- JAVA线程锁及部分特性
- Java线程-新特性
- Java 线程部分详解
- java 8 部分新特性
- 集合及jdk部分新特性
- c++11初识及部分新特性
- Java基础---枚举及部分JDK1.5新特性 (黑马程序员)
- Java生涯——高新技术---枚举及部分JDK1.5新特性
- java高级特性之多线程
- java高级特性之多线程 线程池
- [Java基础笔记]线程部分
- java之线程第二部分
- java regex 正则部分高级特性使用
- 关于java线程的一些特性 启动 中断 及如何退出
- 【JAVA】JAVA线程及锁基础知识-niyuelin
- java实现部分线程的同步。对象锁
- 线程及线程锁
- JAVA基础--集合类详解及问题
- 生产环境常见的HTTP状态码列表
- reorder-list
- 两份offer,算法工程师和java开发岗,如何选择?
- Android之SQLite数据库的使用
- JAVA线程锁及部分特性
- java权限与修饰符
- 腾讯2016校招笔试
- iOS开发 适配iOS10以及Xcode8
- JAVA基础--垃圾回收机制及算法
- Spring创建对象的三种方法之二静态工厂创建(源码)
- Web前端开发规范:CSS书写规范
- leetcode之回文字串库函数的使用
- 搭建基本的UI框架(标题----内容-----导航)