《Posix多线程程序设计》是我读的第一本关于多线程程序设计的书籍。这本书生动且深刻地讲解了多线程程序设计的难点与Pthread库的使用方式,我从中收获颇丰。Pthread作为操作系统接口标准,直接用于应用层开发难免会让人感觉到有些单薄。Java对多线程程序设计模式进行了一定的封装,以方便大家的使用。然而在基础功能上,Java的多线程程序与Pthread其实非常相似,这也是这篇blog是使用这个标题的原因。
-
Mutex(Pthread) vs Lock/synchronized(Java)
Mutex是Pthread提供的最基本的线程同步工具,Mutex的功能突出一个简单粗暴,类似于操作系统中的自旋锁(当然,Mutex会把当前线程挂起来)。被Mutex包裹的代码块,同一时间只能为一个执行流服务(这里的执行流可以简单的认为是线程)。单纯使用Mutex,会使多线程程序锁的粒度过大、执行效率低下。
synchronized关键字其实就是弱化版的Mutex,Lock是一个接口,它是对synchronized的一种优化,实现了类似于Mutex的trylock功能。
private final Lock queueLock = new ReentrantLock(); public void job(){ queueLock.lock(); /* */ queueLock.unlock(); }
- cond(Pthread) vs Condition(Java)
如果说上一条看起来还不是很相似,那么cond和Condition基本上是自家兄弟了,连名字都基本是一样的。其中,cond和mutex是有着密切关系的,Condition与Lock也是如此。可以通过下面的代码简单对比一下:
//Pthread ptread_mutex_lock(&mut); pthread_cond_wait(&cond, &mut); pthread_mutex_unlock(&mut); //Java lock = new ReentrantLock(); condition = lock.newCondition(); condition.await();
从上面的代码能看出来,条件变量与互斥锁之间关系密切,这一点在Pthread与Java中完全一样。
- sem(Pthread) vs Semaphore(Java)
正如前文所说,互斥锁是一种非常粗粒度的锁,它只能来保护一段代码或者单个资源。而信号量则不同,它可以保护多个资源。这一点上,Pthread与Java又是基本完全一样。
//Posix int sem_init(sem_t *sem, int pshared,unsigned value); int sem_post(sem_t *sem); int sem_wait(sem_t *sem); int sem_trywait(sem_t *sem); //Java Semaphore semaphore = new Semaphore(1); public void job() { semaphore.acquire(); /* */ semaphore.release(); }
回头看看,会觉得这篇博客挺水的,大概只是罗列了下Pthread与Java对多线程基本工具的实现。但是说实话,这并不是我写这篇博客的本意。我希望的是这种出奇的相似性能引导出我们对多线程程序的真正思考,能够这些基础工具的设计初衷与背景。下篇博客的主题是解析Java并行库中的高级同步类实现。其实到现在为止,我还没有研究这个主题,但是我相信复杂事物都是由简单事物组成的。所以,下篇blog见!
发表评论