我正在研究Re entrant锁并尝试将其与Synchronize相关联。然而,这两个类都给了我意想不到的结果。我期望arrayList有0到9.但这个值永远不会出现在这两个程序中。请建议。 带锁:
package Threads;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Locking {
Lock lock = new ReentrantLock(true);
ArrayList<Integer> al = new ArrayList<Integer>();
static int count = 0;
public void producer() {
lock.lock();
count++;
al.add(count);
System.out.println(al);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
lock.unlock();
}
// System.out.println("I came out of this block:"+Thread.currentThread().getName());
}
public void consumer() {
}
public static void main(String[] args) {
// ExecutorService ex= Executors.newCachedThreadPool();
ExecutorService ex = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
ex.submit(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
new Locking().producer();
}
});
}
ex.shutdown();
}
}
使用同步:
package Threads;
import java.util.ArrayList;
import java.util.Collections;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class LockwithSynchronize {
ArrayList<Integer> al = new ArrayList<Integer>();
static int count = 0;
public synchronized void producer() {
count++;
al.add(count);
System.out.println(al);
try {
Thread.sleep(5000);
// System.out.println("I came out of this block:"+Thread.currentThread().getName());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
// ExecutorService ex= Executors.newCachedThreadPool();
ExecutorService ex = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
ex.submit(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
new LockwithSynchronize().producer();
}
});
}
ex.shutdown();
}
}
答案 0 :(得分:3)
这有很多问题。
首先,您希望它包含0..9,但您在count++
之前调用al.add(count)
,这意味着您实际上应该期望1..10。
由于您每次都使用新的LockWithSynchronize
或Locking
,因此实际上并没有任何共享锁 - 每个实例都有自己的锁,它永远不会与任何锁冲突其他锁定,这意味着您的count
变量完全不受保护。而且,由于ArrayList
在没有同步的情况下调用多个线程,或者add
或类似情况,您可能会定期收到损坏的ConcurrentModificationException
。
试试这个:
public static void main(String [] args){
ExecutorService ex= Executors.newFixedThreadPool(10);
final Locking producer = new Locking();
for (int i=0; i<10;i++)
{
ex.submit(new Runnable(){
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
producer.producer();
}
});
}
ex.shutdown();
}
请注意,我们不是每次都使用新的Locking
,而是重复使用相同的实例,并且您现在会发生什么:您非常快速地生成十个线程,每个线程在尝试之前等待两秒钟致电producer()
。一个线程获得锁定,而另一个线程获得锁定。获得锁定的那个然后在退出之前等待锁定五秒钟,此时下一个线程获得锁定,等待五秒钟,然后退出等等。所以这将花费近一分钟来运行
类似的修改也修复了另一个。
答案 1 :(得分:0)
您的同步不保护静态变量 - synchonize仅在使用时锁定当前this
对象的监视器。没有produce()调用会等待您发布的代码中的任何其他内容。锁定共享的东西 - 比如说LockWithProducer.class。