Trail: Essential Classes_Lesson: Concurrency2

每个对象都有个监视器,访问同步方法的线程会得到这个对象锁,其他线程只能等待

如果访问的是静态的同步方法,获得的实际上是相应的java.lang.Class的对象锁

 

同步的另一种写法是同步块

 

public void addName(String name) {
    synchronized(this) {//必须指明要获得哪个对象的锁,通常用于更细粒度的控制并发
        lastName = name;
        nameCount++;
    }
    nameList.add(name);
}

但同步块中要小心调用其他对象

 

一个线程在已经拥有这个对象锁的情况下,当然可以多次申请获取对象锁

也就是调用一个同步方法的时候,可以调用同一个对象的另一个同步方法,而无需等待

原子操作是说中间不能停止的操作,或者发生,或者不发生

以下两种属于原子读写:

1.对引用变量的读写,对原始类型的读写(但不包括long和double)

2.volatile变量(包括long,double)

原子操作无需考虑多线程错误

 

如果调用一个同步方法的时候,调用另一个对象的同步方法

恰巧同时,另外一个线程反过来调用,这时候肯定会死锁

两线程都拥有一个对象锁,却互相等待对方先释放

 

如果某个资源要消耗很长时间,而一个线程频繁大量的调用这个资源,会让别的线程经常得不到资源,进入饥饿状态

 

有这种线程,如果得不到资源就做出某种反应,恰巧也有另一个同样的线程相遇了

好比两个人走到了一块,你往左了他也往左,你往右他也往右,如此反复,进入活锁状态

 

public void guardedJoy() {
    // Simple loop guard. Wastes
    // processor time. Don't do this!
    while(!joy) {}//一个长期占用cpu的示例
    System.out.println("Joy has been achieved!");
}
public synchronized void guardedJoy() {//推荐使用同步方法
    // This guard only loops once for each special event, which may not
    // be the event we're waiting for.
    while(!joy) {
        try {
            wait();//并且在循环中加入wait()
        } catch (InterruptedException e) {}
    }
    System.out.println("Joy and efficiency have been achieved!");
}

当调用wait()时,会要求获得对象锁,执行wait()后,会自动释放对象锁并进入暂停状态

如果另一个线程获得这个对象锁并调用了notifyAll(),会唤醒所有等待此锁的线程

 

public synchronized notifyJoy() {
    joy = true;
    notifyAll();
}


第二个线程释放锁后,第一个线程则会重新获得锁,并恢复到刚才wait()的地方继续执行

notify适用于多个线程同一动作的话,随便选一个

 

 

public class Drop {
    // Message sent from producer
    // to consumer.
    private String message;
    // True if consumer should wait
    // for producer to send message,
    // false if producer should wait for
    // consumer to retrieve message.
    private boolean empty = true;

    public synchronized String take() {//同步方法
        // Wait until message is
        // available.
        while (empty) {
            try {
                wait();
            } catch (InterruptedException e) {}
        }
        // Toggle status.
        empty = true;
        // Notify producer that
        // status has changed.
        notifyAll();
        return message;
    }

    public synchronized void put(String message) {
        // Wait until message has
        // been retrieved.
        while (!empty) {
            try { 
                wait();
            } catch (InterruptedException e) {}
        }
        // Toggle status.
        empty = false;
        // Store message.
        this.message = message;
        // Notify consumer that status
        // has changed.
        notifyAll();
    }
}


集合框架中已经有一些并发安全的结构,无需重复编码了

 

如果一个对象是不可更改的,当然无需考虑并发:

1.去掉所有setter方法

2.所有字段都是private final

3.不允许覆盖方法,可以声明为final类,或者改成private构造工厂模式得到实例

4.如果字段是个引用了可更改的其他对象,那么,

不要提供修改那个对象的方法,

不要传递自己给那个对象

不要存储那个对象的引用,必要的话,存储一个深拷贝

5.需要的话,生成一个自己的深拷贝,而不是本身

 

final public class ImmutableRGB {//一个无需考虑并发的类

    // Values must be between 0 and 255.
    final private int red;
    final private int green;
    final private int blue;
    final private String name;

    private void check(int red,
                       int green,
                       int blue) {
        if (red < 0 || red > 255
            || green < 0 || green > 255
            || blue < 0 || blue > 255) {
            throw new IllegalArgumentException();
        }
    }

    public ImmutableRGB(int red,
                        int green,
                        int blue,
                        String name) {
        check(red, green, blue);
        this.red = red;
        this.green = green;
        this.blue = blue;
        this.name = name;
    }


    public int getRGB() {
        return ((red << 16) | (green << 8) | blue);
    }

    public String getName() {
        return name;
    }

    public ImmutableRGB invert() {
        return new ImmutableRGB(255 - red,//返回一个新的对象
                       255 - green,
                       255 - blue,
                       "Inverse of " + name);
    }
}



 

你可能感兴趣的:(concurrency)