java多线程读书笔记6 多线程并发同步的使用(转载)

以上内容均来自于本书和我的自己理解的总结

Java Threads, 3rd Edition [Book] (oreilly.com)

 要记住这个是用"线程同步的要领":同步的目的不是防止所有的race condition(资源竞争问题),而是为了防止有问题的race condition.

选择一种锁机制

If we compare our first implementation of the ScoreLabel class (using synchronized methods) to our second (using an explicit lock), it's easy to conclude that using the explicit lock is not as easy as using the synchronized keyword. With the keyword, we didn't need to create the lock object, we didn't need to call the lock object to grab and release the lock, and we didn't need to worry about exceptions (therefore, we didn't need the try/finally clause). So, which technique should you use? That is up to you as a developer. It is possible to use explicit locking for everything. It is possible to code to just use the synchronized keyword. And it is possible to use a combination of both. For more complex thread programming, however, relying solely on the synchronized keyword becomes very difficult, as we will see.

如果我们将ScoreLabel类的第一个实现(使用同步方法)与第二个实现(使用显式锁)进行比较,很容易得出结论,使用显式锁不如使用synchronized关键字简单。使用关键字,我们不需要创建lock对象,不需要调用lock对象来获取和释放锁,也不需要担心异常(因此,我们不需要try/finally子句)。那么,你应该使用哪种技术呢?这取决于作为开发人员的您。可以对所有内容使用显式锁定。可以只使用synchronized关键字编写代码。而且两者结合使用也是可能的。然而,对于更复杂的线程编程,我们将看到,仅仅依赖synchronized关键字变得非常困难。 

How are the lock classes related to static methods? For static methods, the explicit locks are actually simpler to understand than the synchronized keyword. Lock objects are independent of the objects (and consequently, methods) that use them. As far as lock objects are concerned, it doesn't matter if the method being executed is static or not. As long as the method has a reference to the lock object, it can acquire the lock. For complex synchronization that involves both static and nonstatic methods, it may be easier to use a lock object instead of the synchronized keyword. 

锁类与静态方法有什么关系?对于静态方法,显式锁实际上比synchronized关键字更容易理解。锁定对象独立于使用它们的对象(以及相应的方法)。就锁对象而言,正在执行的方法是否是静态的并不重要。只要方法引用了锁对象,它就可以获取锁。对于涉及静态和非静态方法的复杂同步,使用锁对象而不是synchronized关键字可能更容易。

(扩展阅读:任何一个类都其对应的唯一的一个类对象,就是该类类名.class) 

静态同步方法 static 方法 应该使用class级别的锁,类锁(类级别锁)Xxx.class 就是类级别锁对象

Synchronizing entire methods is the simplest technique, but as we have already mentioned, it is possible that doing so creates a lock whose scope is too large. This can cause many problems, including creating a deadlock situation. It may also be inefficient to hold a lock for the section of code where it is not actually needed. 

同步整个方法是最简单的技术,但正如我们已经提到的,这样做可能会创建范围过大的锁。这可能会导致许多问题,包括造成死锁情况。在实际上不需要锁的代码段中持有锁也可能效率低下 

Using the synchronized block mechanism may also be a problem if too many objects are involved. As we shall see, it is also possible to have a deadlock condition if we require too many locks to be acquired. There is also a slight overhead in grabbing and releasing the lock, so it may be inefficient to free a lock just to grab it again a few lines of code later. Synchronized blocks also cannot establish a lock scope that spans multiple methods.

如果涉及太多对象,使用同步块机制也可能会有问题。正如我们将看到的,如果我们需要获取太多的锁,也有可能出现死锁情况。在抓取和释放锁的过程中也会有轻微的开销,因此释放一个锁只是为了在几行代码之后再次抓取它可能是低效的。同步块也无法建立跨越多个方法的锁定范围。 

——————————————————————————————————————————— 

扩展阅读synchronized关键字的使用

 同步方法与同步块
synchronized method 和synchronized block
即使需要同步化整个method的时候,也是有可能仅使用“同步块”的机制。为了澄清这一点,何时对程序代码块做同步化与何时对整个方法做同步化是由程序设计师的个人爱好来决定的,只要注意到lock scope一定是越小越好就可以了。将整个method同步化是最简单的同步技巧,但是已经提过,如此做有可能让lock scope(锁定的范围)过大。这会引发许多问题,包括了死锁的产生,它也会让确实没有需要的程序段无效率地持有lock。

java语言中的synchronized关键字,这个关键字让我们能够对method与程序块做同步化 synchronized(this){}
——reentrantLock类和 Lock interface.(可以用ReentrantLock类型对象的lock()方法和unlock()方法精确锁的范围)ReentrantLock implements Lock
ReentrantLock是Lock 接口的具体实现。

使用原则:
尽量用synchronized 块而不是synchionized方法,如果能够用可以用ReentrantLock类型对象的lock()方法和unlock()来精确同步代码范围则更好,使用原则是:尽量精确并缩小同步代码的范围

Lock 这个interface

定义如下:
public interface Lock{

void lock();//开始锁定方法
void lockInterruptibly() throws InterruptedException;
boolean tryLock();
boolean tryLock(long tiem,TimeUnit unit) throws InterruptedException;
void unlock();//解除锁定方法
Condition newCondition();

}

最后,使用哪种技术通常是个人偏好的问题。倾向于使用显式锁,主要是因为使用锁接口提供的功能 

如果无法获取得到lock的时候想要执行其他的task该怎么办?Lock interface提供了尝试取得lock的一个选项。
tryLock()这个method。它与lock()方法类似的地方在于如果成功的话,它会抓住lock(即获得锁权)但是与lock()方法不同的是如果tryLock()方法获取到lock它并不会等待。相反地,它会返回boolean值,true代表获取到了“锁权”,false代表获取“锁权”失败,即别的线程现在占用了该锁,通过检查这个boolean值我们可以将thread导向不同的task
,举例来说,如果返回的boolean值为false,我们可以将该thread导向其他不需要取得该lock的task上

What if we want to do other tasks if we can't obtain the lock? The Lock interface provides an option to try to obtain the lock: the tryLock( ) method. It is similar to the lock() method in that if it is successful, it grabs the lock. Unlike the lock() method, if the lock is not available, it does not wait. Instead, it returns with a boolean value of false. If the lock is obtained, the return value is a boolean value of true. By inspecting the return value, we can route the thread to separate tasks: if the value returned is false, for instance, we can route the thread to perform alternative tasks that do not require obtaining the lock.

如果无法获得锁,我们还想执行其他任务怎么办?Lock接口提供了一个尝试获取锁的选项:tryLock()方法。它与lock()方法类似,如果成功,它将获取锁。与lock()方法不同,如果锁不可用,它不会等待。相反,它返回的布尔值为false。如果获得锁,则返回值为布尔值true。通过检查返回值,我们可以将线程路由到单独的任务:例如,如果返回的值为false,我们可以将线程路由到不需要获得锁的其他任务。 

如果我们只想等待一段特定的时间来锁呢?tryLock()方法的重载版本允许您指定等待的最长时间。此方法采用两个参数:一个指定时间单位的数量,另一个指定第一个参数的解释方式的TimeUnit对象。例如,要指定50毫秒,long值设置为50,TimeUnit值设置为TimeUnit。毫秒。TimeUnit类是J2SE 5.0中新增的,它以更容易理解的单位指定时间。在Java的早期版本中,大多数基于时间的功能都是以纳秒或毫秒(取决于方法)为单位指定的。 

This method is similar to the lock() method in that it waits for the lock, but only for a specified amount of time. It is similar to the tryLock() method in that it may return without acquiring the lock: it returns with a value of true if the lock is acquired and false if not.

此方法与lock()方法类似,它等待锁,但只等待指定的时间。它与tryLock()方法类似,因为它可能会在不获取锁的情况下返回:如果获取了锁,则返回值为true,否则返回值为false。 

—————————————————————————————————————————
ReentrantLock这个类实现了Lock这个接口,它是Lock这个接口的一个具体实现。是个重要的工具类。

已经可以看到Lock锁接口提供的功能超过了synchronized关键字提供的功能。通过使用显式锁,开发人员可以自由地解决特定于其程序的问题,而不是被并发问题淹没。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值