5. 线程的同步
多线程的安全问题来自于当不同线程切换时,对同一数据的操作引起的混乱。例如两个线程并发同时对同一个文件修改时就有可能造成异常。对于线程的同步,Java提供了如下几种方式解决:
a. 同步代码块
Java的多线程支持引入同步监视器来解决这个问题。
|
这样一来,任何想要修改制定资源的资源执行时,首先说该资源加锁,在加锁期间其它进程无法修改该资源,而在其修改完成之后便释放对该资源的锁定。从而使得同一时刻只有一条线程处于临界区内,保证了安全。
需要注意的是,同步监视器一般可以由任何对象充当,只要其唯一恒定就可以,通常推荐使用可能被并发访问的共享资源充当同步监视器。
b. 同步方法
在Java中的多线程中,使用synchronized关键字修饰的方法成为同步方法。对于同步方法,就无需指定监视器,该对象本身就是监视器。在同步方法执行的时候,就会首先锁定同步监视器this,synchronized保证了只有一条线程对资源的访问。所以,应该把同步方法定义在需要被独占访问的对象类内部。
c. 同步锁
同步锁是线程同步的另一种机制。使用被声明为final的同步锁作为同步监视器,在方法体执行前首先显式加锁,执行完后在显式的解锁,由于使用Lock对象时每个Lock对象都对应一个被访问的对象,其实也就等同于同步方法的实现机制,保证了线程的同步。
|
以上的各种线程同步机制,其实就是以一个始终恒定不变的对象作为同步监视器。在同步块代码中,虽然方法定义在线程类的内部,但是作为同步监视器的被访问对象是在初始化之后从外部传递到其内部的,具有不变性。而在同步方法机制中,同步监视器就是this对象,当对象初始化时,已经恒定了对象,所以其同步监视器也是不变的。Lock机制和同步方法的机制类似,只不过其监视器是lock,因为当初始化独占访问对象时也会初始化lock,所以也是恒定的。
6. 线程通信
a. 控制线程协调运行的机制(1)
Java中有内置的三种方法对线程进行协调控制,他们属于Object类,但调用的时候要使用同步监视器来调用。
wait()方法使当前线程等待,释放对该同步器的锁定。
notify()方法唤醒该同步器上等待的单个线程,对于唤醒的选择是任意的。
notify()唤醒全部等待的线程。
b. 控制线程协调运行的机制(2)
在使用了Lock对象保证同步的的程序中,同步监视器并非this对象本身,就要使用Condition对象的的方法保证同步。
|
这三个方法的功能同上面的三个方法功能。
c. 使用管道流进行通信
同I/O流中的机制(在I/O学习之后补上该部分)
7. 线程池
线程池在系统启动时即创建大量线程,程序将一个Runnable或者Callable对象传给一个线程池,线程池就会启动一条线程执行该对象的run方法,当run方法执行结束后,该线程不会死亡,而是重新返回线程池成为空闲状态。
|