读书人

并发(3)

发布时间: 2012-09-08 10:48:07 作者: rapoo

并发(三)

1:共享临界资源

非线程安全

public class EvenGenerator extends IntGenerator{private int currentEvenValue = 0;public int next() {currentEvenValue++;currentEvenValue++;return currentEvenValue;}public static void main(String[] args) {EvenChecker.test(new EvenGenerator(), 10);}}class EvenChecker implements Runnable {private IntGenerator generator;public EvenChecker(IntGenerator generator,int ident) {this.generator = generator;}public void run() {while(!generator.isCancled()) {int val = generator.next();if(val%2!=0){System.out.println(val + " not even!");generator.cancled();}}}public static void test(IntGenerator generator,int count) {ExecutorService exe = Executors.newCachedThreadPool();for(int i=0;i<count;i++) {//抢占临街资源:generatorexe.execute(new EvenChecker(generator, count));}exe.shutdown();}}abstract class IntGenerator {private volatile boolean cancled = false;public abstract int next();public void cancled() {cancled = true;}public boolean isCancled() {return cancled;}}

?

输出结果(具体输出几行不确定):

427 not even!
431 not even!
429 not even!

?

2:线程安全

1:基本上所有的并发模式在解决线程冲突问题的时候,都是采用序列化访问共享资源的方案(加锁后,一次只能有一个线程访问)。
2:所有对象自动含有单一的锁(也称为监视器)。在对象上调用任意synchronized方法时,对象都被加锁(其他的加锁方法也不能被其他线程访问,非线程安全的方法可以)
3:如果在类中有超过一个方法在处理临界资源,那么必须同步所有相关的方法

?

synchronized

使用synchronized进行加锁

public synchronized int next() {currentEvenValue++;currentEvenValue++;return currentEvenValue;}
//可以在类的范围内防止对static数据的并发访问public synchronized static void add() {}

?

?Lock

private Lock lock = new ReentrantLock();public int next() {lock.lock();try {currentEvenValue++;currentEvenValue++;lock.unlock();return currentEvenValue;} finally {lock.unlock();}}

?unlock()方法必须放置在finally语句中。return语句必须在try子句中出现,确保unlock()不会过早的发生,从而将数据暴露给第二个任务。

使用synchronized关键字时,需要的代码量少,出错的可能性小,解决特殊问题才用lock对象

synchronized不能尝试获取锁且最终失败,或者尝试一段时间后放弃

public class AttemptLocking {private ReentrantLock lock = new ReentrantLock();public static void main(String[] args) throws InterruptedException {final AttemptLocking al = new AttemptLocking();new Thread() {{setDaemon(true);}public void run(){al.lock.lock();System.out.println("acquired");}}.start();//Thread.yield();TimeUnit.SECONDS.sleep(1);al.untimed();al.timed();}public void untimed() {boolean captured = lock.tryLock();try {System.out.println("tryLock(): "+captured);}finally {if(captured) {lock.unlock();}}}public void timed() {boolean captured = false;try {captured = lock.tryLock(2, TimeUnit.SECONDS);}catch (Exception e) {throw new RuntimeException();} try {System.out.println("tryLock(2,TimeUnit.seconds): " + captured);} finally {if(captured) {lock.unlock();}}}}

?

public class Test {public static void main(String[] args) throws InterruptedException {Box w = new Box();w.put();w.remove();}}class Box {private int i=0;private ReentrantLock lock = new ReentrantLock();public void put() throws InterruptedException {boolean flag = lock.tryLock();System.out.println(flag);if(flag) {try {i++;System.out.println("increment:"+i);TimeUnit.SECONDS.sleep(15);} finally {lock.unlock();}}else {System.out.println("increment 锁不可用");}}public void remove() throws InterruptedException {boolean flag = lock.tryLock();System.out.println(flag);if(flag) {try {i--;System.out.println("decreat:"+i);TimeUnit.SECONDS.sleep(15);} finally {lock.unlock();}} else {System.out.println("decreat 锁不可用");}}}

?

还是没看明白trylock的用法,为什么第一种可以正常的去尝试获取,获取不到锁时就继续执行,第二种还是会发生阻塞

读书人网 >编程

热点推荐