java 多线程设计模式_Java多线程设计模式 笔记(一)

//Gate类表示人通过的门,counter记录人数,pass表示通过方法public class Gate {

private int counter = 0;

private String name = "Nobody";

private String address = "Nowhere";

public synchronized void pass(String name,String address){

this.counter++;

this.name = name;

this.address = address;

check();

}

public synchronized String toString(){

return "No." + counter + ":" +name +","+address;

}

private void check(){

if(name.charAt(0)!=address.charAt(0)){

System.out.println("********"+toString());

}

}

}

思考一:

看到代码中的synchronized,一定要思考“这个synchronized在保护什么呢”

在明确了“保护着什么”之后,接下来就需要思考“其他地方也妥善保护了吗”

当多个地方都使用字段时,虽然这边使用了synchronized保护,但是如果过那边没有保护,那么这个字段最终还是没有被保护。就像虽然把前门和后门都锁好了。但是如果窗户开着,那还是没有任何意义

在这段代码中,pass()与toString()方法都加上了synchronized,保护着字段,但是check()方法却没有加,这是否会成为那扇窗呢?

注意check()方法是private的哦,只被pass()方法调用,而pass()已经声明成了synchronized的,当然check()照样可以声明为synchronized,但可能会降低性能

思考二:

synchronized的保护粒度,如果加上代码如下:

public synchronized void setName(String name){

this.name = name;

}

public synchronized void setAddress(String address){

this.address = address;

}

}

这两个方法确实是synchronized方法,但是如果加上这两个方法,Gate类就不安全了

为什么呢?因为在Gate类中,姓名和方法必须一起赋值。我们将pass方法声明为synchronized,就是为了防止多个线程交错执行赋值操作 。如果定义像setName和setAddress这样的方法,线程就会分别给字段赋值。在保护Gate类时,如果不将字段合在一起保护就没有意义了。

思考三:

不在Gate类中使用synchronized,该如何实现Single Threaded Execution模式呢

编写Mutex类执行互斥处理

public class Mutex {

private boolean busy = false;

public synchronized void lock(){

while(busy){

try {

wait();//busy为true,锁在别的线程,进入entry set

} catch (Exception e) {

// TODO: handle exception

}

}

busy = true;

}

public synchronized void unlock(){

busy = false;

notifyAll();

}

}

限制一:不可以重入

假如某个线程连续连续两个调用lock方法,那么在第二次调用时,由于busy字段已经变为true,所以会执行wait。这就好像自己把自己锁在了门外,称为"非reentrant"

限制二:任何人都可以unlock,即使线程没有调用lock方法,也可以调用unlock方法。这就好像不是自己上的锁,自己也可以打开一样

改良Mutex:

public class Mutex {

private long locks = 0;//当前锁的个数 = lock的调用次数 - unlock的调用次数

private Thread owner = null;

public synchronized void lock(){

Thread me = Thread.currentThread();

while(locks > 0 && owner != me){

try {

wait();

} catch (Exception e) {

// TODO: handle exception

}

}

assert locks == 0 || owner == me;

//lock个数为0,或者自己已经被lock了

owner = me;

locks++;

}

public synchronized void unlock(){

Thread me = Thread.currentThread();

if(locks == 0 || owner != me){

return;

}

assert locks > 0 && owner == me;

//lock个数大于0,而且是自己lock的

locks--;

if(locks == 0){

owner = null;

notifyAll();

}

}

}

改良二:使用ReentrantLock的Mutex类

import java.util.concurrent.locks.ReentrantLock;

public class Mutex extends ReentrantLock{

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值