Akka Concurrency: Concurrency and Parallelism

Parallelism vs. Concurrency

Parallelism: 指两个或两个以上事件或活动在同一时刻发生,并行性使多个程序同一时刻可在不同CPU上同时执行.并行的行为是真正的同时执行,在多核或多个机器上,并且并行是无状态的.

Concurrency: 指两个或两个以上的事件或活动在同一时间间隔内发生。并发的实质是一个物理CPU(也可以多个物理CPU) 在若干道程序之间多路复用,并发性是对有限物理资源强制行使多用户共享以提高效率。

并行是物理上同时发生,并发是逻辑上同时发生.系统中有多个任务同时存在即为并发,系统中有多个任务同时执行则为并发.并发是并行的子集.如果在单核CPU上,只能存在并发而不可能存在并行.

状态共享式并发

首先定义一个简单的User类:

public static class User {
    private String first = "";
    private String last = "";
    public String getFirstName() {
        return this.first;
    }
    public void setFirstName(String s) {
        this.first = s;
    }
    public String getLastName() {
        return this.last;
    }
    public void setLastName(String s) {
        this.last = s;
    }
}

让这个类支持并发,不允许两个不同的线程同时修改属性,因此增加同步属性:

public static class User {
    private String first = "";
    private String last = "";
    synchronized public String getFirstName() {
        return this.first;
    }
    synchronized public void setFirstName(String s) {
        this.first = s;
    }
    synchronized public String getLastName() {
        return this.last;
    }
    synchronized public void setLastName(String s) {
        this.last = s;
    }
}

如果对属性字段使用”volatile”的话效果会不会更好?

public static class User {
    private volatile String first = "";
    private volatile String last = "";
    public String getFirstName() {
        return this.first;
    }
    public void setFirstName(String s) {
        this.first = s;
    }
    public String getLastName() {
        return this.last;
    }
    public void setLastName(String s) {
        this.last = s;
    }
}

但是当你在并发程序中调用这段代码的时候:

user.setFirstName("Spider");
user.setFirstName("Green");
user.setLastName("Man");
user.setLastName("Lantern");
System.out.println(user.getFirstName() + " " + user.getLastName());

你会发现你得到的结果是”Spider Lantern”,这就是真正的问题所在.解决这种问题的办法:

import java.util.concurrent.locks.ReentrantLock;
public static class User {
    private ReentrantLock lock = new ReentrantLock();
    private String first = "";
    private String last = "";
    public void lock() {
        lock.lock();
    }
    public void unlock() {
        lock.unlock();
    }
    public String getFirstName() {
        return this.first;
    }
    public void setFirstName(String s) {
        try { lock();
            this.first = s;
        } finally {
            unlock(); }
    }
    public String getLastName() {
        return this.last;
    }
    public void setLastName(String s) {
        try { lock();
            this.last = s;
        } finally {
            unlock();
        } 
    }
}

整个实现都是在围绕”并发锁”,使用的时候:

try {
    user.lock();
    System.out.println(user.getFirstName() + " " + user.getLastName());
  } finally {
    user.unlock();
}

这样就很好了解决了上面的问题,但是,如果遇到这样的使用情况:

// Thread 1
  user.setFirstName("Green");
// Thread 2
  try {
    user.lock();
    System.out.println(user.getFirstName() + " " + user.getLastName());
  } finally {
    user.unlock();
}
// Thread 1
user.setLastName("Lantern");

同样的错误又发生了.

不可变性