使用信号量阻塞java中的线程
我的目标是让多个线程一次访问一个静态属性“nbPlace”,并减少它。我使用一个变量“mutex”让一个线程每次递减,但是出现了一些问题。这是我的密码:使用信号量阻塞java中的线程,java,multithreading,synchronization,Java,Multithreading,Synchronization,我的目标是让多个线程一次访问一个静态属性“nbPlace”,并减少它。我使用一个变量“mutex”让一个线程每次递减,但是出现了一些问题。这是我的密码: public class Client extends Thread{ static int nbPlace=10; static int mutex=1; public Client(String name){ super(name); } public void run(){ if (mutex==1) {
public class Client extends Thread{
static int nbPlace=10;
static int mutex=1;
public Client(String name){
super(name);
}
public void run(){
if (mutex==1) {
mutex=0;
decrementer(getName());
mutex=1;
} else
try {
join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
static void decrementer(String nomThread){
nbPlace--; System.out.println("dec par "+nomThread+" ... nbplace="+nbPlace);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Client [] t= new Client[5];
for(int i=0;i<5;i++) t[i]=new Client ("thread n° "+i);
for (int i=0;i<5;i++) t[i].start();
}
公共类客户端扩展线程{
静态位置=10;
静态int互斥=1;
公共客户端(字符串名称){
超级(姓名);
}
公开募捐{
如果(互斥=1){
互斥量=0;
递减器(getName());
互斥量=1;
}否则
试一试{
join();
}捕捉(中断异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
}
静态空隙递减器(字符串){
NBoTest-Soal.Out.PrtLn(“DEC PAR”+ NoMeNoT+ +……NbPo位置=“+NbPoT”);
}
公共静态void main(字符串[]args){
//TODO自动生成的方法存根
客户[]t=新客户[5];
对于(int i=0;i当另一个线程在该块中时,如果一个线程遇到If(mutex==1){
条件,它将跳转到else
并调用join()
在当前线程(而不是在另一个线程)上调用join()
,意味着当前线程正在等待自身消亡,这是不可能发生的,因此这些线程将永远阻塞。不,Java中的情况不是这样的。如果没有适当的同步,您无法并发访问可变数据
使此代码安全的最简单方法是:
static int nbPlace = 10;
static final Object object = new Object();
public Client(String name) {
super(name);
}
public void run() {
synchronized (object) {
decrementer(getName());
}
}
Java已经有了信号量实现,只需使用它:
public class Client extends Thread{
static int nbPlace=10;
private final Semaphore sem = new Semaphore(1);
public Client(String name){
super(name);
}
public void run(){
try {
sem.acquire();
decrementer(getName());
sem.release();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
static void decrementer(String nomThread){
nbPlace--; System.out.println("dec par "+nomThread+" ... nbplace="+nbPlace);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Client [] t= new Client[5];
for(int i=0;i<5;i++) t[i]=new Client ("thread n° "+i);
for (int i=0;i<5;i++) t[i].start();
}
}
公共类客户端扩展线程{
静态位置=10;
私有最终信号量sem=新信号量(1);
公共客户端(字符串名称){
超级(姓名);
}
公开募捐{
试一试{
sem.acquire();
递减器(getName());
sem.release();
}捕捉(中断异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
}
静态空隙递减器(字符串){
NBoTest-Soal.Out.PrtLn(“DEC PAR”+ NoMeNoT+ +……NbPo位置=“+NbPoT”);
}
公共静态void main(字符串[]args){
//TODO自动生成的方法存根
客户[]t=新客户[5];
对于(inti=0;iAndy Turner在评论中所说的是正确的,请使用倒计时闩锁
我不同意接受的答案,因为如果try-catch失败,那么信号量将永远不会释放。您应该始终在finally块中释放。锁定代码的最简单方法是同步块
public synchronized void myMethod(){
//anything here is only able to be run by one thread at a time
}
同步的另一种形式是
public class MyClass {
final Object lock = new Object();
public void myMethod(){
synchronized(lock){
//anything here is only able to be run by one thread at a time
}
}
也可以使用可重入锁
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MyClass{
final Lock lock = new ReentrantLock();
public void myMethod(){
lock.lock();
try{
//anything here is only able to be run by one thread at a time
}finally{
lock.unlock();
}
}
}
还有ReadWriteLock,只要线程没有写锁,它就允许无限线程读取
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class MyClass {
final ReadWriteLock rwlock = new ReentrantReadWriteLock();
public void myReadMethod(){
Lock lock = rwlock.readLock();
lock.lock();
try{
//anything here is only able to be run
//by any thread that is reading as long
//as another thread doesn't have the write lock
}finally{
lock.unlock();
}
}
public void myWriteMethod(){
Lock lock = rwlock.writeLock();
lock.lock();
try{
//anything here is only able to be run by one thread at a time
}finally{
lock.unlock();
}
}
}
我从来没有使用过信号量,所以我不能谈论它们。为什么不让你的减量器方法同步化呢?“出错了”你能说得更具体一点吗?有没有一个好的理由不使用原子整数或倒计时锁存器?或者信号量呢?我希望所有的线程减量都是“nbPlace”,但只有第一个做到了。如果你让它变得易变,会有帮助吗?(还有互斥)