Java5多线程---Lock
在Java5中的并发包java.util.concurrent.locks 下有个接口Lock ,这个接口是实现同步访问的另外一种形式,Lock为锁和等待条件提供一个框架的接口,它不同于内置同步和监视器。以前我们都是在用synchronized 关键字,用于修饰方法(同步方法)或者同步代码块来实现同步访问,在java5中我们可以用Lock来实现同步的访问。我们都知道用关键字synchronized修饰的方法或者synchronized代码块,当一个线程获取对应的监控器(对象锁)时候,并执行synchronized里面的代码的时候,其它线程会一直处于等待此线程释放监视器才有机会进行执行,此线程释放监视器有两种,一是此线程执行完毕,二是出现异常java虚拟机会让其自动释放监视器。
试想下在当前获取监视器的线程进行耗时的操作(如:进行IO操作或者直接说进行休眠),那么其它线程将无限的进行等待下去。synchronized方法或者 synchronized代码块执行完毕之后会自动释放监视器,而Lock需要用户自己手动释放,但lock 是更细粒度控制同步问题。
一、Lock
1、Lock是 java.util.concurrent.locks包下的一个接口,它实现提供了比使用synchronized方法和语句可获得的更广泛的锁定操作。锁变成了更加的灵活性,也带来了更多的责任。我们不使用块结构锁就事情了synchronized方法和代码块时会自动释放功能,大多数情况下,应该使用以下语句
Lock l = ...;
l.lock();
try {
// access the resource protected by this lock
} finally {
l.unlock();
}
锁定和取消锁定出现在不同的作用访问中时,必须谨慎地确保保持锁定时的所有执行的所有代码块用try-finally 货try-catch 加以保护,用于确保在必要时候释放锁的作用。所有Lock实现都必须实时与监视器锁提供的相同内存同步:成功的lock操作与成功的Lock操作具有相同的内存同步效应,成功的unlock操作与成功的Unlock操作具有相同的内存同步效应
2、接口方法说明
void lock();
void lockInterruptibly();
Condition newCondition();
boolean tryLock();
boolean tryLock(long time,TimeUnit unit);
void unlock()
void lock() 方法获取锁,如果当前锁不可用,出于禁用当前的线程,并且在获得锁之前,该线程将处于休眠状态。unlock释放锁,当前持有监视器(锁)释放出来,让给其它线程持有机会具体用法代码如下:
package java5;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* lock的用法
* @author dongtian
* @date 2015年6月15日 下午3:49:27
*/
public class LockTest {
static Lock lock = new ReentrantLock();
private static class Thread1 extends Thread {
@Override
public void run() {
lock.lock();
System.err.println(Thread.currentThread().getName() +"获取锁");
try {
for (int i = 0; i < 10; i++) {
System.err.println("当前线程" +Thread.currentThread().getName());
Thread.currentThread().sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
System.err.println(Thread.currentThread().getName() +"释放锁");
}
}
}
public static void main(String[] args) {
Thread1 thread1 = new Thread1();
Thread1 thread2 = new Thread1();
thread1.start();
thread2.start();
}
}
输出结果:是线程0执行10次,完成释放锁然后线程1获取锁执行10次然后释放锁
Thread-0获取锁
当前线程Thread-0
当前线程Thread-0
当前线程Thread-0
当前线程Thread-0
当前线程Thread-0
当前线程Thread-0
当前线程Thread-0
当前线程Thread-0
当前线程Thread-0
当前线程Thread-0
Thread-0释放锁
Thread-1获取锁
当前线程Thread-1
当前线程Thread-1
当前线程Thread-1
当前线程Thread-1
当前线程Thread-1
当前线程Thread-1
当前线程Thread-1
当前线程Thread-1
当前线程Thread-1
当前线程Thread-1
Thread-1释放锁
boolean tryLock()方法是尝试获取锁,是在仅在锁空闲状态才获取该锁并立即返回 (true) 否则返回false 如果没有获取空闲的锁则不会再次尝试,我们可以用一个循环轮询获取锁具体案例代码:
package java5;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* trylock的用法
* @author dongtian
* @date 2015年6月15日 下午3:49:27
*/
public class TryLock {
static Lock lock = new ReentrantLock();
private static class Thread1 extends Thread {
@Override
public void run() {
while (!lock.tryLock()) {
System.err.println("当前线程 "+ Thread.currentThread().getName() +" 正在尝试获取锁");
}
System.err.println("当前线程 "+ Thread.currentThread().getName() +" 获取锁成功!");
try {
for (int i = 0; i < 10; i++) {
System.err.println("当前线程" +Thread.currentThread().getName());
Thread.currentThread().sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
System.err.println(Thread.currentThread().getName() +"释放锁");
}
}
}
public static void main(String[] args) {
Thread1 thread1 = new Thread1();
Thread1 thread2 = new Thread1();
thread1.start();
thread2.start();
}
}
输出结果:
当前线程 Thread-0 正在尝试获取锁
当前线程 Thread-0 获取锁成功!
当前线程 Thread-1 正在尝试获取锁
...
当前线程 Thread-1 正在尝试获取锁
当前线程 Thread-1 正在尝试获取锁
当前线程 Thread-1 正在尝试获取锁
当前线程 Thread-1 正在尝试获取锁
当前线程 Thread-1 正在尝试获取锁
当前线程 Thread-1 正在尝试获取锁
Thread-0释放锁
当前线程 Thread-1 获取锁成功!
当前线程Thread-1
当前线程Thread-1
当前线程Thread-1
当前线程Thread-1
当前线程Thread-1
当前线程Thread-1
当前线程Thread-1
当前线程Thread-1
当前线程Thread-1
当前线程Thread-1
Thread-1释放锁
boolean tryLock(long time,TimeUnit unit) 如果给定的锁在给定的时间内空闲,并且当前线程没有被中断,则可以获取该锁并立即返回,否则已经超过指定的等待的事件则会返回,此方法不会阻塞。具体方法如下:
package java5;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* trylock的用法
* @author dongtian
* @date 2015年6月15日 下午3:49:27
*/
public class TryLock {
static Lock lock = new ReentrantLock();
private static class Thread1 extends Thread {
@Override
public void run() {
try {
while (!lock.tryLock(1000,TimeUnit.SECONDS)) {
System.err.println("当前线程 "+ Thread.currentThread().getName() +" 正在尝试获取锁");
}
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
System.err.println("当前线程 "+ Thread.currentThread().getName() +" 获取锁成功!");
try {
for (int i = 0; i < 10; i++) {
System.err.println("当前线程" +Thread.currentThread().getName());
Thread.currentThread().sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
System.err.println(Thread.currentThread().getName() +"释放锁");
}
}
}
public static void main(String[] args) {
Thread1 thread1 = new Thread1();
Thread1 thread2 = new Thread1();
thread1.start();
thread2.start();
}
}
输出结果如下:
当前线程 Thread-0 获取锁成功!
当前线程Thread-0
当前线程Thread-0
当前线程Thread-0
当前线程Thread-0
当前线程Thread-0
当前线程Thread-0
当前线程Thread-0
当前线程Thread-0
当前线程Thread-0
当前线程Thread-0
Thread-0释放锁
当前线程 Thread-1 获取锁成功!
当前线程Thread-1
当前线程Thread-1
当前线程Thread-1
当前线程Thread-1
当前线程Thread-1
当前线程Thread-1
当前线程Thread-1
当前线程Thread-1
当前线程Thread-1
当前线程Thread-1
Thread-1释放锁
lockInterrupt() 方法,如果当前线程未被中断,则获取锁。如果锁可用,则获取锁,并立即返回;如果锁不可用,出于线程调度目的,将禁用当前线程具体代码如下:
package java5;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* lock的用法
* @author dongtian
* @date 2015年6月15日 下午3:49:27
*/
public class LockInterruptTest {
static Lock lock = new ReentrantLock();
private static class Thread1 extends Thread {
@Override
public void run() {
System.err.println(Thread.currentThread().getName() +"获取锁");
try {
lock.lockInterruptibly();
for (int i = 0; i < 10; i++) {
System.err.println("当前线程" +Thread.currentThread().getName());
Thread.currentThread().sleep(100);
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
System.err.println(Thread.currentThread().getName() +"释放锁");
}
}
}
public static void main(String[] args) {
Thread1 thread1 = new Thread1();
Thread1 thread2 = new Thread1();
thread1.start();
thread2.start();
}
}
二、ReadWriteLock
ReadWriteLock 唯一的一个实现类 ReentrantReadWriteLock 维护了一对相关的锁一个用于只读操作,一个用于写入操作。只要没有writer 读取锁可以由多个reader线程同时保存。写入锁是独占的。在高并发的多线程的情况下虽然异常只有一个线程可以修改共享数据名单上在任何多个线程可以同时读取共享数据,读-写锁利用了这一点。从理论上将,与互斥相比,使用读-写锁允许并发性增强将带来更大的性能提高,在实践中,只有在多个处理器上并且只有访问模式适用于共享数据时候,才能完全实现并发性的增强。
ReadWriteLock接口方法
(1)Lock readLock();
(2) Lock writeLock();
package java5;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/***
*
* @author dongtian
* @date 2015年6月15日 下午4:48:56
*/
public class CachedData {
ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
public void progress() {
readWriteLock.readLock().lock();
//读操作
String readData = reader.readLine();
readWriteLock.readLock().unlock();
readWriteLock.writeLock().lock();
write.write(readData);
readWriteLock.writeLock().unlock();
}
}
说明:如果一个线程占有读锁的时候,那么其它申请写锁会一直处于等待状态。
如果一个线程占有写锁的时候,那么其它线程申请读锁或者写锁会一直处于等待状态。
分享到:
相关推荐
在Java多线程编程中,线程间的通信是非常重要的概念,用于协调多个并发执行的任务。线程的状态转换是理解线程通信的基础,主要包括四个状态:新(New)、可执行(Runnable)、死亡(Dead)和停滞(Blocked)。新状态...
在Java编程中,多线程是并发处理任务的关键技术,特别是在服务器端开发和高并发场景下。本篇文章将深入探讨“最简单的线程安全问题”,并结合相关源码和工具来帮助理解。线程安全问题通常涉及到多个线程对共享资源的...
在本项目"java多线程实现-tcp端口扫描"中,我们利用多线程技术来加速TCP端口扫描的过程。TCP(Transmission Control Protocol)是一种面向连接的、可靠的传输协议,广泛应用于网络通信中。端口扫描是网络安全检测和...
Java多线程是Java编程中的重要概念,它允许程序同时执行多个任务,提高了系统的效率和响应性。在Java中,实现多线程主要有两种方式:继承Thread类和实现Runnable接口。接下来,我们将深入探讨这两个方法以及相关的...
Java多线程技术是编程中不可或缺的一部分,它允许程序在同一时间执行多个任务,从而提高效率和响应速度。本文将深入探讨多线程相关的概念。 首先,我们要了解程序、进程和线程的区别。程序是一组指令的集合,静态...
### Java多线程知识点总结及企业真题解析 #### 一、知识点总结 ##### (1)多线程相关概念 1. **程序、进程和线程的区分**: - **程序**:为了完成特定的任务而编写的指令集合。它是静态的概念。 - **进程**:...
### Java多线程-避免同步机制带来的死锁问题及用Lock锁解决线程安全问题 #### 死锁 ##### 1. 说明 在多线程编程中,死锁是一种常见的问题,指的是两个或多个线程在执行过程中,因为竞争资源而造成的一种相互等待...
在“多线程-day02”的学习资源中,我们深入探讨了Java内存模型以及多线程的特性与控制机制。 **Java内存模型** Java内存模型,也称为JVM内存模型,是Java程序员理解和掌握的基础知识,特别是在进行并发编程时。它...
Java多线程-线程的安全问题与线程的同步机制介绍 在 Java 多线程编程中,线程安全问题是非常重要的一个话题。当多个线程访问同一个资源时,如果只有读操作那么不会出现线程安全问题,但是如果多个线程对资源进行读...
本教程主要探讨如何在Java中利用多线程技术高效地与Oracle数据库进行交互,从而实现更强大的并发处理能力。通过"Java操作Oracle数据库-多线程.rar"这个压缩包,我们可以学习到以下几个关键知识点: 1. **JDBC连接**...
Java 多线程机制是Java语言的一大特性,它允许程序同时执行多个任务,模拟现实生活中的并发行为。在Java中,创建线程有两种主要方式:继承Thread类和实现Runnable接口。 在例子1中,我们看到一个简单的多线程示例。...
### Java多线程—线程间的通信 #### 一、线程间的通信 ##### (1)为什么要处理线程间的通信? 在多线程环境中,不同的线程可能需要协同工作来完成一项任务。例如,一个线程负责生产数据,另一个线程负责消费这些...
在Java多线程编程中,线程安全问题是非常关键的概念,它涉及到多个线程访问共享资源时可能出现的数据不一致或异常情况。本题主要通过两个练习题来加深对线程安全的理解。 ### 练习题1:新年倒计时 #### 题目描述 ...
Java的多线程是编程中一个重要的概念,尤其在服务器端和高并发应用中不可或缺。在Java中,多线程允许程序同时执行多个任务,提高了系统资源的利用率和程序的响应速度。 首先,理解线程的基本概念至关重要。线程是...
《Java多线程编程实战指南-核心篇》是一本深入探讨Java并发编程的书籍,旨在帮助读者掌握在Java环境中创建、管理和同步线程的核心技术。Java的多线程能力是其强大之处,使得开发者能够在同一时间执行多个任务,提高...
这个“JAVA-多线程 所有文件”压缩包很可能包含了一系列关于Java多线程学习的源代码示例和相关文档。下面我们将深入探讨Java多线程的相关知识点。 1. **线程的概念**:线程是操作系统分配CPU时间的基本单位,一个...
本主题将深入探讨如何在Java多线程环境下实现进度条功能。 首先,理解Java多线程的基本概念至关重要。Java通过Thread类和Runnable接口来支持多线程。创建一个新线程通常有两种方式:继承Thread类并重写run()方法,...
### JAVA中的单线程与多线程概念解析 #### 单线程的理解 在Java编程环境中,单线程指的是程序执行过程中只有一个线程在运行。这意味着任何时刻只能执行一个任务,上一个任务完成后才会进行下一个任务。单线程模型...
在探索多线程和设计模式的同时,还要关注线程间的通信(如使用`wait()`、`notify()`、`notifyAll()`等)、同步机制(如`synchronized`关键字、`Lock`接口等)、线程池的使用(`ExecutorService`、`...
Java多线程是Java编程中的一个重要概念,它允许程序同时执行多个任务,提高了程序的效率和响应速度。在Java中,实现多线程有两种主要方式:继承Thread类和实现Runnable接口。 1. 继承Thread类: 当我们创建一个新...