??xml version="1.0" encoding="utf-8" standalone="yes"?>wait
?code>notify ?notifyAll
Q分解成截然不同的对象,以便通过这些对象与L Lock
实现l合使用Qؓ(f)每个对象提供多个{待 set Qwait-setQ。其中,Lock 替代?synchronized Ҏ(gu)和语句的使用Q?tt>Condition 替代?Object 监视器方法的使用?
下面解释?font face="Courier New">Condition api里面的例?生者,消费?Q?br />
public class ConditionTest {
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition(); //生者的前提条gQ没有达到次条g阻?br /> final Condition notEmpty = lock.newCondition(); //消费者的前提条gQ没有达到次条g阻?br />
final Object[] items = new Object[100];
int putptr, takeptr, count;
//生
public void put(Object x) throws InterruptedException {
lock.lock();
try {
while (count == items.length)//如果满了(jin)Q就让需要条件ؓ(f)Q没满的的线E?生?{?br /> notFull.await();
items[putptr] = x;
if (++putptr == items.length) putptr = 0;
++count;
notEmpty.signal();//如果已经生?jin),p需要条件ؓ(f)不ؓ(f)I的U程(消费?执行
} finally {
lock.unlock();
}
}
//消费
public Object take() throws InterruptedException {
lock.lock();
try {
while (count == 0)//如果为空p需要条件ؓ(f)不ؓ(f)I的U程(消费?{?br /> notEmpty.await();
Object x = items[takeptr];
if (++takeptr == items.length) takeptr = 0;
--count;
notFull.signal();//如果消费?jin),p条gZ满的U程(生?执行
return x;
} finally {
lock.unlock();
}
}
}
public class RreadWriteLockTest {
ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
public int i = 0;
//d
public void read() throws InterruptedException{
readWriteLock.readLock().lock();//获取读锁
System.out.println("read thread:"+Thread.currentThread().getName());
Thread.sleep(10000);
System.out.println("read:"+i);
readWriteLock.readLock().unlock();
}
//写入
public void write() throws InterruptedException{
readWriteLock.writeLock().lock();//获取写锁
System.out.println("write thread:"+Thread.currentThread().getName());
Thread.sleep(10000);
i = 2;
System.out.println("write:"+i);
readWriteLock.writeLock().unlock();
}
}
试代码Q?br />1 试两个同时ȝQ结果都能同时读取?br />2 试一个读Q一个写的,需要其中一个释N之后才能q行另外一个操?br />public static void main(String[] args) throws InterruptedException {
final RreadWriteLockTest lockTest= new RreadWriteLockTest();
new Thread(new Runnable() {
@Override
public void run() {
try {
lockTest.write();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
Thread.sleep(2000);
new Thread(new Runnable() {
@Override
public void run() {
try {
lockTest.read();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
}
打印如下Q?br />write thread:Thread-0执行完之?10U之?才执行read thread:Thread-1
注意Q执行完以后一定要执行unlockQ要不lock的计数没?1Q这样对应read或者write的操作将无法q行Q一直等待?/span>
举例来说Q?/p>
public synchronized void method(){
method body
}
{h(hun)?/p>
public void method(){
this.intrinsicLock.lock();
try{
method body;
}finally(){
this.intrinsicLock.unlock();
}
}
从上面的代码CZ可以看出Qsynchronized的用方式是比较单的。这也导致了(jin)大量的初学者在到java~程的时候落入陷阱里Q认为既然synhronized可以搞定一切,那么不管三七二十一Q只要有q发可能性的地方Q就加上synchronized的关键字Q这昄是不对的。在java对象中,q个java对象只有q一个内部锁Q其中一个synchronizedҎ(gu)获取C(jin)q个锁,另外一个synchronizedҎ(gu)的调用将被阻塞?/p>
?/p>
class sync{
public synchronized void methodA(){};
public synchronized void methodB(){};
... ...
}
methodA 和methodB在初始就是互斥的Q如果methodA和methodBq入互相{待Q就很容易出现死锁的情况。那如果到q种情况Q应该怎么做了(jin)Q常用的方式是在Ҏ(gu)内部新徏一个无意义的对象,然后对这个无意义的对象加锅?/p>
另外需要注意的是将?rn)态类声明为synchronizedҎ(gu)也是合法的。D例来_(d)如果Sync有一个static synchronizedҎ(gu)Q那么这个方法被调用?bank.classq个cd象本w在jvm中将被锁?/p>
AtomicIntegerQ一个提供原子操作的Integer的类。在Java语言中,++i和i++操作q不是线E安全的Q在使用的时候,不可避免的会(x)用到synchronized关键字。而AtomicInteger则通过一U线E安全的加减操作接口?/p>
来看AtomicInteger提供的接口?/p>
//获取当前的?/p>
public final int get()
//取当前的|q设|新的?/p>
public final int getAndSet(int newValue)
//获取当前的|q自?/p>
public final int getAndIncrement()
//获取当前的|q自?/p>
public final int getAndDecrement()
//获取当前的|q加上预期的?/p>
public final int getAndAdd(int delta)
... ...
我们在上一节提到的CAS主要是这两个Ҏ(gu)
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
public final boolean weakCompareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
q两个方法是名称不同Q但是做的事是一L(fng)Q可能在后箋(hu)的java版本里面?x)显C出区别来?/p>
详细查看?x)发玎ͼq两个接口都是调用一个unsafe的类来操作,q个是通过JNI实现的本地方法,l节׃考虑?jin)?/p>
下面是一个对比测试,我们写一个synchronized的方法和一个AtomicInteger的方法来q行试Q直观的感受下性能上的差异
l果
time elapse:31
time elapse:16
由此不难看出Q通过JNI本地的CAS性能q超synchronized关键?/p>
Reference
http://stackoverflow.com/questions/2443239/java-atomicinteger-what-are-the-differences-between-compareandset-and-weakcompar