用Java编写互斥体
我是计算机科学的新手,正在读一本介绍线程和互斥体的书。我曾经尝试过用Java编写一个互斥体,它似乎大部分时间都能正常工作,但有时却不行 在我的代码中,critical部分将数字1到10添加到静态变量j中,结果是55(如果j从0开始)。如果我在临界区同时运行三个线程,我会得到j的随机最终值,这是有意义的 但是使用下面的互斥锁,大多数时候我会得到一个最终的j值165(55*3),这是我想要的,但是有时候,我会得到随机的j值。有人能看看我的代码,看看是怎么回事吗?谢谢用Java编写互斥体,java,multithreading,mutual-exclusion,Java,Multithreading,Mutual Exclusion,我是计算机科学的新手,正在读一本介绍线程和互斥体的书。我曾经尝试过用Java编写一个互斥体,它似乎大部分时间都能正常工作,但有时却不行 在我的代码中,critical部分将数字1到10添加到静态变量j中,结果是55(如果j从0开始)。如果我在临界区同时运行三个线程,我会得到j的随机最终值,这是有意义的 但是使用下面的互斥锁,大多数时候我会得到一个最终的j值165(55*3),这是我想要的,但是有时候,我会得到随机的j值。有人能看看我的代码,看看是怎么回事吗?谢谢 public class Myt
public class Mythread extends Thread {
private static int j = 0;
private static int mutex = 0; // Initial value of the mutex is 0;
@Override
public void run() {
while (test_and_set(mutex) == 1) {
// wait here if mutex is 1
System.out.println("Thread waiting..");
}
for (int i = 1; i <= 10; i++) { // Start of Critical section
j += i; //
}
System.out.println(j); // End of Critical section
// Should add on 55 to j if one thread is running through the CS
mutex = 0; // Thread that has finished the CS sets the mutex to 0.
}
public static int test_and_set(int oldMutexValue) {
if (mutex == 0) {
mutex = 1;
}
return oldMutexValue;
}
}
public class Test1 {
public static void main(String[] args) {
Mythread thread1 = new Mythread();
Mythread thread2 = new Mythread();
Mythread thread3 = new Mythread();
thread1.start();
thread2.start();
thread3.start();
}
}
公共类Mythread扩展线程{
私有静态int j=0;
private static int mutex=0;//互斥的初始值为0;
@凌驾
公开募捐{
while(测试_和_集(互斥)==1){
//如果互斥量为1,请在此处等待
System.out.println(“线程等待…”);
}
对于(int i=1;i,您的任务有java.util.concurrency.Semaphore类:
package test;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class MyThread extends Thread {
private static int j = 0;
private static final Semaphore mutex = new Semaphore(1, true);
@Override
public void run() {
try {
while (!mutex.tryAcquire(100, TimeUnit.MILLISECONDS)) {
System.out.println("Thread waiting.");
}
}
catch (InterruptedException e) {
System.out.println("Thread interrupted.");
return;
}
try {
for (int i = 1; i <= 10; i++) { // Start of Critical section
j += i; //
}
System.out.println(j); // End of Critical section
// Should add on 55 to j if one thread is running through the CS
}
finally {
mutex.release(); // Thread that has finished the CS sets the mutex to 0.
}
}
}
封装测试;
导入java.util.concurrent.Semaphore;
导入java.util.concurrent.TimeUnit;
公共类MyThread扩展线程{
私有静态int j=0;
私有静态最终信号量互斥=新信号量(1,true);
@凌驾
公开募捐{
试一试{
而(!mutex.tryAcquire(100,时间单位.毫秒)){
System.out.println(“线程等待”);
}
}
捕捉(中断异常e){
System.out.println(“线程中断”);
返回;
}
试一试{
对于(int i=1;i),您创建了<强>竞争条件,使用<强>旋转锁。在java中不建议使用旋转锁。请考虑以下内容:
public class MyThread extends Thread {
private static int j = 0;
public void run() {
synchronized(this) {
for (int i = 1; i <= 10; i++) {
j += i;
}
}
System.out.println(j);
}
一个线程开始执行,另两个线程等待。另外两个线程等待。另外两个线程现在都同时设置互斥量并开始执行,给你一个奇数J值,因为它们都在同时改变它
要修复:
实现Javasynchronized方法。synchronized是Java处理线程安全和控制的内部方法。没有旋转锁
将您的MyThread更改为以下内容:
public class MyThread extends Thread {
private static int j = 0;
public void run() {
synchronized(this) {
for (int i = 1; i <= 10; i++) {
j += i;
}
}
System.out.println(j);
}
公共类MyThread扩展线程{
私有静态int j=0;
公开募捐{
已同步(此){
对于(int i=1;i(1)您的test_和_set()函数看起来应该模拟在许多计算机体系结构中实现的同名硬件指令。但是test_和_set()应该返回什么?提示:它应该告诉调用方调用方是否“赢得”互斥锁
(2) 你的test_和_set()有一个更大的问题:它不是原子的。如果你想知道为什么一台有“test”指令和“set”指令的计算机也需要有test_和_set(也称为TAS)指令,那是因为TAS指令是原子的。我猜你需要了解更多关于这意味着什么(见下面的4)
(3) TAS是古老的。现代计算机实现了一种更强大的称为比较和交换或比较和设置(CAS)的功能。如果你想了解现代同步算法的工作原理,你应该使用CAS而不是TAS
Java标准库有一个真正的原子CAS函数,您可以调用它:Java.util.concurrent.atomic.AtomicInteger.CompareAndSet(…)
(4) 在您有更多的使用经验之前,您可能不应该尝试学习如何编写同步函数/对象。让您感到遗憾的是,您没有同步您的test_和_set()函数。如果您不知道怎么做,那么您就没有太多编写多线程代码的经验
首先学习如何使用同步对象。然后你可以担心它们是如何实现的。你的关键部分不受任何同步的保护。@MarkWvolatile
在测试和设置
中没有帮助。动作不是原子的。很好@SotiriosDelimanolis@SotiriosDelimanolis你能解释一下你的意思吗n通过同步?我对这一点很陌生。编辑:事实上,这在我的书后面会介绍,所以我会继续读下去!阅读比赛条件。回答得好,但不是针对OP提出的问题。OP不想使用同步
:他/她正试图通过编写自己的版本来学习同步
的工作原理当然。synchronized(这个)
在这里实际上没有帮助。多个线程需要在一个单一的共享对象上进行同步。我喜欢在引擎盖下实现细节的提示!特别高兴看到这个答案,因为OP显然是在问这个问题,哈哈。