1、对synchronized的改进
JDK5后引入了线程并发库java.util.concurrent。JSR 166小组花了这么多时间来开发java.util.concurrent.lock框架呢?答案很简单——synchronized同步是不错,但它并不完美,有一些功能性的限制:没法中断一个正在等候得到锁的线程,也没法经过投票获得锁,若是不想等下去也就无法获得锁。同步还要求锁的释放只能在与得到锁所在的堆栈帧相同的堆栈帧中进行,多数状况下这没问题,并且与异常处理交互得很好,但确实存在一些非块结构的锁定更合适的状况。
2、ReentrantLock类
java.util.concurrent.lock中的Lock框架是锁定的一个抽象,它容许把锁定的实现做为Java类,而不是做为语言的特性来实现。这就为Lock的多种实现留下了空间,各类实现可能有不一样的调度算法、性能特性或者锁定语义。ReentrantLock类实现了Lock,它拥有与synchronized相同的并发性和内存语义,可是添加了相似锁投票、定时锁等候和可中断锁等候的一些特性。此外它还提供了在激烈争用状况下更佳的性能,也就是说当许多线程都想访问共享资源时,JVM能够花更少的时候来调度线程,把更多时间用在执行线程上。
Reentrant锁意味着什么呢?简单来讲它有一个与锁相关的获取计数器,若是拥有锁的某个线程再次获得锁,那么获取计数器就加1,而后锁须要被释放两次才能得到真正释放。这模仿了synchronized的语义:若是线程进入由线程已经拥有的监控器保护的synchronized块,就容许线程继续进行,当线程退出第二个或者后续synchronized 块时不释放锁,只有线程退出它进入的监控器保护的第一个synchronized块时才释放锁。
lock必须在finally块中释放。不然若是受保护的代码将抛出异常,锁就有可能永远得不到释放,忘记在finally块中释放锁很是麻烦。而使用synchronized同步,JVM将确保锁会得到自动释放。
3、代码对比
synchronized同步
public class SynchronizeOutput
{
public synchronizedvoid output(String name)
{
for (int i = 0; i < name.length(); i++)
{
System.out.print(name.charAt(i));
}
System.out.println();
}
}
public class SynchronizeTest
{
public static void main(String[] args)
{
final SynchronizeOutput synOutput = new SynchronizeOutput();
for (int i = 0; i < 100; i++)
{
new Thread(new Runnable() {
public void run()
{
synOutput.output("I am xy");
}
}).start();
}
}
}
Lock
public class LockOutput
{
Lock lock = new ReentrantLock();
public void output(String name)
{
lock.lock();
try
{
for (int i = 0; i < name.length(); i++)
{
System.out.print(name.charAt(i));
}
System.out.println();
}
finally
{
lock.unlock();
}
}
}
public class LockTest
{
public static void main(String[] args)
{
final LockOutput lockoutput = new LockOutput();
for (int i = 0; i < 100; i++)
{
new Thread(new Runnable() {
public void run()
{
lockoutput.output("I am xy");
}
}).start();
}
}
java
}算法
原帖地址:http://blog.csdn.net/fw0124/article/details/6672522多线程