Lock比传统线程模型中的Synchronied方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象.两个线程执行的代码段要实现同步互斥的效果,它们必须用同一个Lock对象,锁是在代表要操作的资源的类的内部方法中,而不是线程代码中.
class & interface
* Lock
interface of lock,
* ReentrantLock
basic implementation of Lock
*
* Condition
interface of condition,
*
* ReadWriteLock
interface, read/write version of Lock,
* ReentrantReadWriteLock
basic implementation of ReadWriteLock,
*
(1)下面看下Lock的使用方法:
package thread.lock;
import java.util.Random;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockTest1 {
public static void main(String[] args) {
ShareCache shareCache = new ShareCache();
for (int i = 0; i < 20; i++) {
if (i % 2 == 0) {
// create 10 write number thread
ThreadFactory.createWriteThread(shareCache).start();
}else{
// create 10 read number thread
ThreadFactory.createReadThread(shareCache).start();
}
}
}
}
class ThreadFactory {
private static Random random = new Random();
public static Thread createWriteThread(final ShareCache shareCache) {
return new Thread(new Runnable() {
@Override
public void run() {
shareCache.incrementNumber();
}
});
}
public static Thread createReadThread(final ShareCache shareCache) {
return new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()
+ " read number:" + shareCache.getNumber());
}
});
}
}
class ShareCache {
private Lock lock = new ReentrantLock();
private int number = 0;
// number increment
public void incrementNumber() {
lock.lock();
try {
Thread.sleep(1000);
number++;
System.out.println(Thread.currentThread().getName()
+ " increment number:" + number);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
// 读数据可以不上锁
public int getNumber() {
int returnValue = 0;
lock.lock();
try {
// 模拟读取数据的时间
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
returnValue = number;
lock.unlock();
return returnValue;
}
}
输出结果:
Thread-0 increment number:1
Thread-1 read number:1
Thread-3 read number:1
Thread-5 read number:1
Thread-7 read number:1
Thread-9 read number:1
Thread-2 increment number:2
Thread-6 increment number:3
Thread-11 read number:3
Thread-13 read number:3
Thread-4 increment number:4
Thread-15 read number:4
Thread-10 increment number:5
Thread-17 read number:5
Thread-8 increment number:6
Thread-19 read number:6
Thread-12 increment number:7
Thread-14 increment number:8
Thread-16 increment number:9
Thread-18 increment number:10
Java多线程 Condition的使用
Condition
将 Object
监视器方法(wait
、notify
和 notifyAll
)分解成截然不同的对象,以便通过将这些对象与任意 Lock
实现组合使用,为每个对象提供多个等待 set(wait-set)。其中,Lock
替代了synchronized
方法和语句的使用,Condition
替代了 Object 监视器方法的使用。
条件(也称为条件队列 或条件变量)为线程提供了一个含义,以便在某个状态条件现在可能为 true 的另一个线程通知它之前,一直挂起该线程(即让其“等待”)。因为访问此共享状态信息发生在不同的线程中,所以它必须受保护,因此要将某种形式的锁与该条件相关联。等待提供一个条件的主要属性是:以原子方式 释放相关的锁,并挂起当前线程,就像 Object.wait
做的那样。
Condition
实例实质上被绑定到一个锁上。要为特定 Lock
实例获得 Condition
实例,请使用其newCondition()
方法。
下面写个Lock和Condition结合的使用方法:
package thread.lock;
import java.util.Random;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LockConditionTest {
public static void main(String[] args) {
ShareObj obj = new ShareObj() ;
new Thread(new Producer(obj)).start() ;
new Thread(new Customer(obj)).start() ;
}
}
class ShareObj{
private Object shareData =null ;
private Random random = new Random() ;
private Lock lock = new ReentrantLock() ;
private Condition condition = lock.newCondition() ;
public void produceData() throws InterruptedException{
lock.lock() ;
while(shareData !=null){
condition.await() ;
}
System.out.println("produce data......");
Thread.sleep(1000) ;
int data = random.nextInt(100) ;
System.out.println("produce data:"+data);
shareData = new Integer(data) ;
condition.signal() ;
lock.unlock() ;
}
public void customerData() throws InterruptedException{
lock.lock() ;
while(shareData ==null){
condition.await() ;
}
System.out.println("custome data......");
Thread.sleep(1000) ;
System.out.println("customer data:"+shareData);
shareData = null ;
condition.signal() ;
lock.unlock() ;
}
}
class Producer implements Runnable{
private ShareObj shareObj ;
public Producer(ShareObj obj){
this.shareObj = obj ;
}
@Override
public void run() {
while(true){
try {
shareObj.produceData() ;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class Customer implements Runnable{
private ShareObj shareObj ;
public Customer(ShareObj obj){
this.shareObj = obj ;
}
@Override
public void run() {
while(true){
try {
shareObj.customerData() ;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}