Java 并发编程(一)

多线程同步内部如何实现

wait/notify, synchronized, ReentrantLock, 等

 

synchronized: 重量级 调用操作系统的函数

jdk1.6以前

private native void start0(); ---调用openjdk中的c文件---c文件调用操作系统函数---启动线程

JVM中的线程=操作系统中的线程 线程同步会使CPU由用户态切换为内核态

jdk1.7以后

尽量由JVM解决

 

Thread.yield()方法作用是:暂停当前正在执行的线程对象,并执行其他线程。

yield()应该做的是让当前运行线程回到可运行状态,以允许具有相同优先级的其他线程获得运行机会。因此,使用yield()的目的是让相同优先级的线程之间能适当的轮转执行。但是,实际中无法保证yield()达到让步目的,因为让步的线程还有可能被线程调度程序再次选中。

结论:yield()从未导致线程转到等待/睡眠/阻塞状态。在大多数情况下,yield()将导致线程从运行状态转到可运行状态,但有可能没有效果。

 

LockSupport.park(); LockSupport封装了unsafe中的park()

park立即阻塞线程

unpark获取许可继续运行

 

 

 

实现一把锁的基本思路

park+自旋

volatile int status=0;

Queue parkQueue;//队列

void lock(){

while(!compareAndSet(0,1)){//判断status能不能加锁,如果=0则变为1加锁成功,等于1则加锁失败

//

park();

}

//lock 20s

.....

unlock();

}

void unlock(){

status=0;

lock_notify();

}

void park(){

将当前线程加入到等待队列

parkQueue.add(currentThread);

//将当前线程释放cpu 阻塞

releaseCpu();

}

void lock_notify(){

//得到要唤醒的队列首线程

Thread t = parkQueue.header();

//唤醒等待线程

LockSupport.unpark(t);

}

将unlock放在finally{}中,确保即使抛出异常也会释放锁。

 

 

 

ReentrantLock中的abstract void lock()有两个实现类

FairSync 公平锁

NonfairSync 非公平锁

默认构造方法是非公平锁 static ReentrantLock l = new ReentrantLock();

加true参数是公平锁 static ReentrantLock l = new ReentrantLock(true);

 

ReentrantLock出现的原因是1.6之前synchronized关键字不管是线程并发竞争执行还是交替执行都是重量级锁,都会调用操作系统的函数,C++,ReentrantLock在交替执行时是轻量级锁

1.7以后ReentrantLock与synchronized没有区别

但是ReentrantLock提供了丰富的api

你可能感兴趣的:(Java)