我的目标是让许多线程访问静态attribut" nbPlace"一个时间,并减少它。我使用变量"互斥"让一个线程每次都减少,但是出了点问题。这是我的代码:
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();
}
}
答案 0 :(得分:1)
Andy 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();
}
}
}
我从未使用信号量,所以我不能说它们。
答案 1 :(得分:0)
如果线程在该块中有另一个线程时遇到if (mutex==1) {
条件,则跳转到else
并调用join()
。
在当前线程上调用join()
(不在另一个线程上)意味着当前线程正在等待自己死亡,这不会发生,所以这些线程永远阻塞。
答案 2 :(得分:0)
不,在Java中,事情不会这样。如果没有适当的同步,您无法同时访问可变数据。
使此代码安全的最简单方法是:
static int nbPlace = 10;
static final Object object = new Object();
public Client(String name) {
super(name);
}
public void run() {
synchronized (object) {
decrementer(getName());
}
}
答案 3 :(得分:0)
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();
}
}