您的位置:首页 > 编程语言 > Java开发

Java的高并发编程系列(五)reentrantlock替换synchronized

2018-03-29 14:43 821 查看
java高并发编程主要有下面三个组成:

1.同步器synchronized

2.同步容器

3.线程池:threadPool、executort

本例中由于test1锁定this,只有test1执行完毕的时候,test2才能执行:

public class ReentrantLock1 {
public synchronized void test1(){
for (int i = 0; i < 10; i++) {
System.out.println(i);
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void test2(){
System.out.println("execute test2........");
}
public static void main(String[] args) {
ReentrantLock1 rl = new ReentrantLock1();
new Thread(rl::test1).start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(rl::test2).start();
}
}


使用reentrantlock可以完成同样的功能, 需要注意的是,必须要必须要必须要手动释放锁(重要的事情说三遍)。使用syn锁定的话如果遇到异常,jvm会自动释放锁,但是lock必须手动释放锁,因此经常在finally中进行锁的释放。

public class ReentrantLock2 {
Lock lock = new ReentrantLock();
public void test1(){
try {
lock.lock(); //synchronized(this)
for (int i = 0; i < 10; i++) {
System.out.println(i);

TimeUnit.SECONDS.sleep(1);
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally { //必须手动释放
lock.unlock();
}
}
public void test2(){
lock.lock();
System.out.println("execute test2........");
lock.unlock();
}
public static void main(String[] args) {
ReentrantLock2 rl = new ReentrantLock2();
new Thread(rl::test1).start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(rl::test2).start();
}
}


使用reentrantlock可以进行“尝试锁定”tryLock,这样无法锁定,或者在指定时间内无法锁定,线程可以决定是否继续等待。

public class ReentrantLock3 {
Lock lock = new ReentrantLock();
public void test1(){
try {
lock.lock(); //synchronized(this)
for (int i = 0; i < 10; i++) {
System.out.println(i);

TimeUnit.SECONDS.sleep(1);
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally { //必须手动释放
lock.unlock();
}
}
/**
* 可以使用tryLock进行尝试锁定,不管锁定与否,方法都将继续执行
* 可以根据tryLock的返回值来判定是否锁定
* 也可以指定tryLock的时间,由于tryLock(time)抛出异常,所以要注意unclock的处理,必须放到finally中
*/
public void test2(){
boolean locked = false;
try {
lock.tryLock(6, TimeUnit.SECONDS);
System.out.println("test2...." + locked);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (locked) {
lock.unlock();
}
}
}
public static void main(String[] args) {
ReentrantLock3 rl = new ReentrantLock3();
new Thread(rl::test1).start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(rl::test2).start();
}
}


使用ReentrantLock还可以调用lockInterruptibly方法,可以对线程interrupt方法做出响应,在一个线程等待锁的过程中,可以被打断。

public class ReentrantLock4 {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
Thread t1 = new Thread(()->{
try {
lock.lock();
System.out.println("t1 start");
TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
System.out.println("t1 end");
} catch (InterruptedException e) {

4000
System.out.println("interrupted!");
} finally {
lock.unlock();
}
});
t1.start();
Thread t2 = new Thread(()->{
try {
//lock.lock();
lock.lockInterruptibly(); //可以对interrupt()方法做出响应
System.out.println("t2 start");
TimeUnit.SECONDS.sleep(5);
System.out.println("t2 end");
} catch (InterruptedException e) {
System.out.println("interrupted!");
} finally {
lock.unlock();
}
});
t2.start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.interrupt(); //打断线程2的等待
}
}


ReentrantLock还可以指定为公平锁

public class ReentrantLock5 extends Thread{

private static ReentrantLock lock = new ReentrantLock(true); //参数为true表示为公平锁,请对比输出结果

@Override
public void run() {
for (int i = 0; i < 100 ; i++) {
lock.lock();
try {
System.out.println(Thread.currentThread().getName() + "获得锁");
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
public static void main(String[] args) {
ReentrantLock5 rl = new ReentrantLock5();
Thread t1 = new Thread(rl);
Thread t2 = new Thread(rl);
t1.start();
t2.start();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  高并发编程