一,前言
众所周知,一个可靠的多线程程序必须要能够坐到无死锁,无饥饿。
什么叫做无饥饿:如果一个线程需要获得一个Lock,那么这个操作在一个有限时间内最终会获得成功(不论时间长短)。
那么我们现在就来实现只有两个线程的Lock。
二,Lock接口
public interface Lock{
public void lock();
public void unlock();
}
三,只有两个线程的Lock实现
public class TwoThreadLockImpl implements Lock {
private boolean[] flag = new boolean[2];
public void lock() {
/**获得当前线程Id(0或者1)
**/
int threadId = ThreadUtil.getCurrentThread(); step 1
flag[threadId ] = true; step 2
/**循环等待另一个线程将标志位设置为false;
**/
while(!flag[1- threadId] ) { step 3
}
/**
这个地方标志着一个线程已经获得这个Lock
**/
}
public void unlock() {
int threadId = ThreadUtil.getCurrentThread();
将标志位设置为false,让另外一个线程可以获得这个锁。
boolean[threadId ] = false;
}
}
但是这个Lock实现有个缺陷,如果执行方式如下:
线程A 线程B
1 step 1
2 step1
3 step 2
4 step 2
5 step 3
6 step 3
在执行第5,6两步的时候 会发生死锁。即两个线程谁也永远不能得到这个锁。
四,这个实现是个正确的实现吗?即这个实现满足互斥特性吗?
定义如下,如果一个线程在一获得锁与释放锁之间的执行时间为Ca,定义两个线程在时间上的 偏序为Ca > Cb表示 Ca在Cb之前先发生。一个正确的锁必须满足互斥,要么Ca>Cb要么Cb > Ca。
这个a,b表示线程ID
证明如下:
假设这个Lock实现不满足互斥特性:即Ca Cb没有时间上的偏序关系。
即Ca Cb之间有交集
|-----------Ca--------------------------|
-----------------------------------|----------------------|------------------|-------------------------|-----
|----------------------Cb------------------|
红色的部分为时间交集。
通过阅读代码可以得到:
线程a: write(a)(flag(a) = true) > read(a)(flag(b) == false) > Ca -----------1
线程b: write(b)(flag(b) = true) > read(b)(flag(a) == false) > Cb -----------2
我们又注意到,在标志位被设置为true 到 释放锁之前不会被重置。即:
如果a想获得lock必须得等到b执行flag(b) = false之后,才会读取到read(a)(flag(b) == false)-------->即a想获得锁必须得等到b执行完unlock之后,反过来b想获得锁也得等到a执行完unlock之后,即要么Ca > Cb要么Cb > Ca.与证明假设矛盾。即此lock实现满足互斥特性。
分享到:
相关推荐
在Java编程语言中,实现多线程文件传输是一种优化程序性能、提高系统资源...在提供的`java多线程文件传输`压缩包中,可能包含了实现这些概念的示例代码,通过分析和学习,可以更好地理解多线程文件传输的原理和实践。
本主题将深入探讨如何在Java多线程环境下实现进度条功能。 首先,理解Java多线程的基本概念至关重要。Java通过Thread类和Runnable接口来支持多线程。创建一个新线程通常有两种方式:继承Thread类并重写run()方法,...
本项目以"java多线程实现大批量数据导入源码"为题,旨在通过多线程策略将大量数据切分,并进行并行处理,以提高数据处理速度。 首先,我们需要理解Java中的线程机制。Java通过`Thread`类来创建和管理线程。每个线程...
《JAVA多线程教学演示系统》是一篇深入探讨JAVA多线程编程的论文,它针对教育领域中的教学需求,提供了一种生动、直观的演示方式,帮助学生更好地理解和掌握多线程技术。这篇论文的核心内容可能包括以下几个方面: ...
`synchronized`是Java中用于实现线程同步的关键字之一。它可以用来修饰方法或者代码块,确保被修饰的代码在同一时刻只能被一个线程访问。这是Java实现线程安全的一种基本手段。 ##### 使用synchronized修饰方法 当...
了解并熟练掌握这些Java多线程的概念和实践技巧,对于编写高性能、并发友好的Java应用至关重要。在实际开发中,合理地使用多线程可以提高程序的运行效率,但也需要考虑到线程安全、资源竞争等问题,避免出现死锁、...
Java多线程与并发编程是Java开发中至关重要的一部分,它涉及到如何高效地利用CPU资源,以实现程序的并行执行。在操作系统层面,多任务和多进程是通过分配不同的内存空间来实现的,而线程则共享同一进程的内存,这...
Java多线程是Java编程中的一个重要概念,它允许程序同时执行多个任务,提高了程序的效率和响应速度。在Java中,实现多线程有两种主要方式:继承Thread类和实现Runnable接口。 1. 继承Thread类: 当我们创建一个新...
Java多线程是Java编程中的重要概念,它允许程序同时执行多个任务,极大地提升了程序的效率和性能。在Java中,实现多线程有两种主要方式:通过实现Runnable接口或者继承Thread类。本案例将深入探讨Java多线程中的关键...
在Java编程中,多线程并发是提升程序执行效率、充分利用多核处理器资源的重要手段。本文将基于"java 多线程并发实例"这个主题,深入探讨Java中的多线程并发概念及其应用。 首先,我们要了解Java中的线程。线程是...
在Java编程领域,多线程技术是实现并发执行任务的关键,尤其在开发高并发应用时,如本例中的“抢红包”程序。本程序利用Java的多线程特性,模拟了现实生活中多人同时抢红包的场景。以下是这个抢红包程序涉及的一些...
本主题将深入探讨如何使用Java的并发包(java.util.concurrent)来实现多线程对数据库数据的批量处理,包括增、删、改等操作。 首先,我们需要了解Java中的线程基础。线程是程序执行的最小单位,一个进程可以包含多...
最后,Java并发库还包含了很多其他有用的工具,如Semaphore(信号量)用于控制同时访问特定资源的线程数量,CyclicBarrier(循环屏障)和CountDownLatch(计数器门锁)用于多线程间的协作,以及Lock接口及其实现如...
Java多线程编程是Java平台的核心特性之一,特别是在Java 5之后,其并发包`java.util.concurrent`提供了更强大和高效的工具,使得开发者能够更好地管理线程资源,提高应用程序的性能和可伸缩性。本篇文章将深入探讨...
一、Java多线程基础 1. 线程的创建:Java提供了两种创建线程的方式——继承Thread类和实现Runnable接口。继承Thread类可以直接创建一个新的线程类,而实现Runnable接口则可以将线程逻辑封装在任何类中,更利于代码...
这份“JAVA多线程编程技术PDF”是学习和掌握这一领域的经典资料,涵盖了多线程的全部知识点。 首先,多线程的核心概念包括线程的创建与启动。在Java中,可以通过实现Runnable接口或继承Thread类来创建线程。创建后...
Java多线程是Java编程中的核心概念,它允许程序同时执行多个任务,提高了系统的效率和响应性。在Java中,多线程的实现主要通过两种方式:继承Thread类和实现Runnable接口。理解并掌握多线程的使用对于任何Java开发者...
本项目通过Java多线程技术来实现这一目标,为初学者提供了一个良好的实践平台。 首先,理解多线程的概念至关重要。在单线程环境中,程序按照顺序执行任务,而在多线程环境中,多个任务可以同时运行,提高了计算机的...
在Java编程中,多线程下载文件是一种优化大文件下载速度和效率的技术。它通过将一个大文件分割成多个小部分,然后同时启动多个线程分别下载这些部分,从而达到加速下载的效果。以下是对这个主题的详细解释: 1. **...