concurrent API提供了一个名为Lock的类,它将序列化控件以访问关键资源。它给出了park()和unpark()等方法。
如果我们可以使用synchronized关键字并使用wait()和notify() notifyAll()方法,我们也可以做类似的事情。
我想知道哪一个在实践中更好,为什么?
concurrent API提供了一个名为Lock的类,它将序列化控件以访问关键资源。它给出了park()和unpark()等方法。
如果我们可以使用synchronized关键字并使用wait()和notify() notifyAll()方法,我们也可以做类似的事情。
我想知道哪一个在实践中更好,为什么?
当前回答
锁和同步块都有相同的目的,但这取决于使用情况。考虑以下部分
void randomFunction(){
.
.
.
synchronize(this){
//do some functionality
}
.
.
.
synchronize(this)
{
// do some functionality
}
} // end of randomFunction
在上述情况下,如果一个线程进入同步块,另一个块也被锁定。如果在同一个对象上有多个这样的同步块,则所有的同步块都被锁定。在这种情况下,可以使用java.util.concurrent.Lock来防止不必要的块锁定
其他回答
主要的区别是公平性,换句话说,请求是FIFO处理还是可以有驳船?方法级同步确保公平或FIFO分配锁。使用
synchronized(foo) {
}
or
lock.acquire(); .....lock.release();
不能保证公平。
如果您对锁有很多争用,那么您很容易遇到barging,即新请求获得锁而旧请求卡住。我曾经见过这样的情况:为了一个锁,200个线程在短时间内到达,而第二个到达的线程最后被处理。这对于某些应用程序是可行的,但对于其他应用程序则是致命的。
请参阅Brian Goetz的《Java并发实践》一书中的13.3节,以获得关于此主题的完整讨论。
你可以实现java.util.concurrent中的实用程序使用低级原语(如synchronized、volatile或wait / notify)所做的所有事情
然而,并发性是棘手的,大多数人至少在某些方面犯了错误,导致他们的代码要么不正确,要么效率低下(或两者兼而有之)。
并发API提供了更高级的方法,使用起来更容易(因此也更安全)。简而言之,你不应该再直接使用synchronized、volatile、wait、notify了。
Lock类本身在这个工具箱的底层,你甚至不需要直接使用它(你可以使用queue和Semaphore等等,大多数时候)。
如果只是锁定一个对象,我更喜欢使用synchronized
例子:
Lock.acquire();
doSomethingNifty(); // Throws a NPE!
Lock.release(); // Oh noes, we never release the lock!
你必须显式地在所有地方执行try{} finally{}。
而对于synchronized,它非常清楚,不可能出错:
synchronized(myObject) {
doSomethingNifty();
}
也就是说,对于更复杂的事情,锁可能更有用,因为你无法以如此干净的方式获取和释放。老实说,我更倾向于在一开始就避免使用裸锁,而只是使用更复杂的并发控制,如CyclicBarrier或LinkedBlockingQueue,如果它们满足您的需求的话。
我从来没有使用wait()或notify()的理由,但可能有一些好的理由。
锁和同步的主要区别:
使用锁,您可以以任何顺序释放和获取锁。 使用synchronized,您只能按照获取锁的顺序释放锁。
锁和同步块都有相同的目的,但这取决于使用情况。考虑以下部分
void randomFunction(){
.
.
.
synchronize(this){
//do some functionality
}
.
.
.
synchronize(this)
{
// do some functionality
}
} // end of randomFunction
在上述情况下,如果一个线程进入同步块,另一个块也被锁定。如果在同一个对象上有多个这样的同步块,则所有的同步块都被锁定。在这种情况下,可以使用java.util.concurrent.Lock来防止不必要的块锁定