本文节选自 Effective Java by Joshua Bloch 和 Concurrent Programming in Java by Doug Lea.
1.1 概述
多线程程序设计比单线程程序设计要困难的多,所以,如果一个库中的类能够帮助你从低层的多线程程序设计中解脱出来,那么一定要使用这个类。比如java.util.Timer。另外,util.concurrent包是一个高层次的线程工具集合。在 Java 语言中,协调对共享字段的访问的传统方法是使用同步,确保完成对共享字段的所有访问。对于现代 JVM 而言,无竞争的同步现在非常便宜。以下是两个简单例子:
public class SynchronizedCounter
{
private int value;
public synchronized int getValue() { return value; }
public synchronized int increment() { return ++value; }
public synchronized int decrement() { return --value; }
}
public class SynchronizedMutex
{
private Thread curOwner = null;
public synchronized void acquire() throws InterruptedException
{
if (Thread.interrupted()) throw new InterruptedException();
while (curOwner != null)
{
wait();
}
curOwner = Thread.currentThread();
}
public synchronized void release()
{
if (curOwner == Thread.currentThread())
{
curOwner = null;
notify();
}
else
{
throw new IllegalStateException("not owner of mutex");
}
}
}
1.2 synchronized关键字
1.2.1 语义
synchronized关键字不属于方法签名的一部分。所以当子类覆盖父类的方法时,synchronized修饰符不会被继承。因此接口中的方法不能被声明为synchronized。同样地,构造函数也不能被声明为synchronized(尽管构造函数内的程序块可以被声明为synchronized)。
在java语言中,锁是递归(recursive)的,锁操作是基于“每线程”而不是“每调用”,如果调用线程已经拥有了锁,当他试图再次获得锁的时候,即使此时该锁保护的数据上有另一个完全不相关的操作正在进行,它也会成功。本质上讲,这时候该锁没有起到应有的作用。递归锁简化了多线程面向对象程序的设计和构造,但是可能会把活性失败(liveness failure)变成安全性失败(safety failure)。锁的申请和释放操作是在使用synchronized关键字的时候根据内部的获得-释放协议来使用的。所有的锁都是块结构。当进入synchronized方法或块的时候得到锁,退出的时候释放锁,即使因为异常也会释放锁。
1.2.2作为类成员函数的修饰符
当把synchronized关键字作为类成员函数的修饰符时,这时候锁定的是被调用同步方法的对象, 例如
public synchronized int increment() { return ++value; }
实际上等同于
public int increment()
{
synchronized(this)
{
return ++value;
}
}
子类和父类的方法使用同一个锁,但是内部类的锁和它的外部类无关,然而,一个非静态的内部类可以锁住它的外部类,例如:
synchronized(OuterClass.this){ /* body */ }
1.2.3作为类静态函数的修饰符
锁住一个对象并不代表不可访问这个对象或者其任何父类的静态数据。可以通过synchronized static方法或块来实现静态数据的保护。当把synchronized关键字作为类静态函数的修饰符时,这时候锁定的是被调用同步方法的类对象,和每个类相关的静态锁与任何其它类的锁都没有关系,包括它的父类。如果想在子类中增加一个静态同步方法来达到保护父类的静态数据的目的是不可能的,应该用明确同步块版本。以下是synchronized关键字作为类静态函数的修饰符的例子:
public synchronized static int increment() { return ++value; }
实际上等同于
public int increment()
{
synchronized(SynchronizedCounter.class)
{
return ++value;
}
}
1.2.4同步块
当有一个明确的对象作为同步锁的时候, 就可以使用同步块。另外, 如果只是想同步一段代码,那么可以创建一个特殊的对象来充当锁
public void foo(Object obj)
{
synchronized(obj)
{
// do something
}
}
分享到:
相关推荐
java concurrent 阻塞队列 线程 里面有详细的例子,下载后请认真阅读里面的内容,可能有点难以理解,请耐心
Java Concurrent in practice (animated)
java concurrent 包 详细解析
使用java concurrent调用xmlp api生成pdf
JAVA的CONCURRENT用法详解.pdf
java concurrent 多线程 PPT
资深Java专家10年经验总结,全程案例式讲解,首本全面介绍Java多线程编程技术的专著 结合大量实例,全面讲解Java多线程编程中的并发访问、线程间通信、锁等最难突破的核心技术与应用实践 封底 Java多线程无处不在,...
1. java.util.concurrent - Java 并发工具包 2. 阻塞队列 BlockingQueue 3. 数组阻塞队列 ArrayBlockingQueue 4. 延迟队列 DelayQueue 5. 链阻塞队列 LinkedBlockingQueue 6. 具有优先级的阻塞队列 ...
Java Concurrent处理并发需求.txt
java并发工具包 java.util.concurrent中文版pdf
详细的java 多线程相关知识 并附有相关练习题
java concurrent包分类结构图
EBS java concurrent program的实现
java.util.concurrent系列文章(1) java.util.concurrent系列文章(1) java.util.concurrent系列文章(1) java.util.concurrent系列文章(1)
java同步大杀器concurrent 包java同步大杀器concurrent 包java同步大杀器concurrent 包java同步大杀器concurrent 包java同步大杀器concurrent 包java同步大杀器concurrent 包java同步大杀器concurrent 包java同步大...
JUC使用指导手册 http://tutorials.jenkov.com/java-util-concurrent/blockingqueue.html 中文译文
1.打开cmd,cd到jdk的path,本机是:cd C:\Java\jdk6\bin 2.资源javaConcurrentAnimated.jar放在D盘根目录 3.使用java -cp命令: java -cp D:\javaConcurrentAnimated.jar vgrazi.concurrent.samples.launcher....
Concurrent Programming in Java - Design Principles and Patterns
JAVAConcurrent Programming in Java 对于一些JAVA 理解
资源JavaConcurrent实用知识库分享知识分享