JAVA核心技术总结(十四章)多线程

2017-03-10  本文已影响0人  五月的约修亚
  1. 例子
class ThreadTask implements Runnable //在1.5以后加入了callable接口
{
    public void run()
    {    
        //.....
    }
}
ThreadTask task = new ThreadTask();
Thread t = new Thread(task);
t.start();
  1. 锁对象
    假定第一个线程调用transfer方法,在执行结束前被剥夺了运行权。假定第二个线程也调用transfer,由于第二个线程不能获得锁,将在调用lock方法时被阻塞,必须等第一个线程unlock后才能被激活。
    每个Bank对象都有自己的ReentrantLock,如果两个线程访问同一个Bank对象,锁以串行的方式提供服务,但是如果每个线程访问不同的Bank对象将得到不同的锁对象,不会发生阻塞
public class Bank
    Lock bankLock = new ReentrantLock();//定义锁
    Condition sufficientFunds = bankLock.newCondition(); //定义条件
    public void transfer(int from, int to, int amount)
    {
            bankLock.lock(); //加锁
            try{
            while(! (ok to proceed)) //条件变量不满足
                Con.await();  //该线程被阻塞并且放弃了锁,等待其他线程通过signalAll来激活自己重新进入该while循环继续执行
                //do something
                Con.signalAll(); //当该线程做了某些事情后,其他线程的条件变量可能被满足,所以通过signalAll来激活等待该条件的所有线程,让它们继续尝试运行
            }
            finally{
                bankLock.unlock();//解锁
            }
    }
}
  1. synchronized关键字用于保护整个方法(能用synchronized就不要自己使用Lock/Condition)
public synchronized void transfer(int from, int to, int amount) throws InterruptedException
{
    while(!(ok to proceed))
        wait();  //同条件变量的wait
        //do something
        notifyAll();  //同条件变量的signalAall
    }
}
  1. volatile
    声明为volatile的变量每次使用时都要重新从内存中读取(因为其有可能被其他线程改变,所以不能信任预取在寄存器中的值)

  2. 线程局部变量
    有时为了避免共享变量,使用ThreadLocal辅助类为各个线程提供各自的实例。

  3. 读写锁

private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private Lock readLock = rwl.readLock()
private Lock writeLock = rwl.writeLock()

对所有读方法加锁

void read()
{
    readLock.lock();
    //do something
    readLock.unlock();
}

对所有写方法加锁

void write()
{
    writeLock.lock();
    //do something
    writeLock.unlock();
}
  1. 线程中断
    首先来看Thread类三个和中断有关的方法:
    ==interrupt方法不会真的终止线程运行,而只是设定中断的标志位,然后由线程本身决定如何处理这个中断==
    理解Java线程的中断
    《Java并发编程》之线程中断与终止线程运行
    每个线程都有一个与之相关联的 Boolean 属性,用于表示线程的中断状态(interrupted status)。中断状态初始时为 false;当另一个线程通过调用 Thread.interrupt() 中断一个线程时,会出现以下两种情况之一。
public class Thread {
    // 发出一个中断请求,把标志位设定为中断状态,不会终止线程运行。
    // 其他线程试图调用该方法,会检测是否有权限中断该线程(正常情况
    // 下不会存在权限问题,这里可以忽略)
    public void interrupt() { ... }

    // 检测标志位是否为中断的状态
    public boolean isInterrupted() { ... }

    // 清除当前线程的标志位的中断状态,返回是否为中断状态
    public static boolean interrupted() { ... }
}
  1. java编程语言中没有任何东西可以避免或打破死锁现象,必须由程序员仔细设计程序确保不会出现死锁。
上一篇下一篇

猜你喜欢

热点阅读