本文节选自 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
}
}
分享到:
相关推荐
1. **Java并发库(java.util.concurrent)** Java并发库是Java SE 5.0引入的一个重要特性,它提供了很多高级并发工具,如线程池、同步容器、并发集合以及阻塞队列等,极大地简化了并发编程。 2. **阻塞队列...
Java Concurrent in practice (animated)
Java并发包(java.concurrent)是Java平台中处理多线程编程的核心工具包,它提供了丰富的类和接口,使得开发者能够高效、安全地编写多线程程序。这个包的设计目标是提高并发性能,减少同步代码的复杂性,并提供高级...
JAVA的CONCURRENT用法详解.pdf
这里我们关注的是如何使用`java.concurrent`包中的工具和XML Processing API(通常指的是JAXB或DOM4J等处理XML的库)来高效地生成PDF。下面将详细解释这个过程以及涉及的相关知识点。 首先,`java.concurrent`包是...
资深Java专家10年经验总结,全程案例式讲解,首本全面介绍Java多线程编程技术的专著 结合大量实例,全面讲解Java多线程编程中的并发访问、线程间通信、锁等最难突破的核心技术与应用实践 封底 Java多线程无处不在,...
1. java.util.concurrent - Java 并发工具包 2. 阻塞队列 BlockingQueue 3. 数组阻塞队列 ArrayBlockingQueue 4. 延迟队列 DelayQueue 5. 链阻塞队列 LinkedBlockingQueue 6. 具有优先级的阻塞队列 ...
### Java并发工具包 `java.util.concurrent` 知识点详解 #### 一、引言 随着多核处理器的普及和应用程序复杂度的增加,多线程编程成为了现代软件开发不可或缺的一部分。为了简化并发编程的复杂性,Java 5 引入了 `...
java concurrent包分类结构图
EBS java concurrent program的实现
### Java Concurrent处理并发需求 #### 一、Java并发基础与Concurrent API介绍 在现代软件开发中,尤其是在服务器端应用中,对并发处理的需求日益增长。为了满足这种需求,Java平台提供了一系列强大的工具和API来...
1. Java并发编程机制 在Java早期版本中,实现多线程主要依赖`Thread`类和`Runnable`接口。`Thread`类可以直接创建线程,而`Runnable`接口则允许将任务逻辑封装在实现了该接口的类中,然后通过`Thread`的构造函数传递...
《Java并发编程实战》还会讨论`java.util.concurrent`包中的高级并发工具,如`ExecutorService`和`Future`,它们可以方便地管理和控制线程池,提高系统的并行处理能力。`CountDownLatch`、`CyclicBarrier`和`...
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 中文译文
Java的并发库提供了一系列工具和API,如`java.util.concurrent`包,帮助开发者有效地管理并发任务。本书主要涵盖以下几个方面: 1. **线程基础**:书中首先介绍了线程的基本概念,包括如何创建和管理线程,以及线程...
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....
Java平台提供了丰富的API支持并发编程,如`java.util.concurrent`包下的各种类和接口,这些工具可以帮助开发者更高效地管理多线程环境下的任务调度和数据共享问题。 ### Java并发编程基础 #### 1. 多线程基础 - **...
"java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError" 是一个典型的错误提示,它表明在并发执行过程中遇到了内存不足的问题。下面我们将深入探讨这个问题的原因、影响以及如何解决。 内存溢出...