为什么我在 Java 中使用锁和条件在这个生产者-消费者中遇到死锁?
Why am I getting a deadlock in this producer-consumer in Java using locks and conditions?
我是 Java 的新手,我正在尝试学习 Java 并发。我已经为生产者-消费者问题(单一生产者和消费者)编写了一个简单的代码。似乎存在死锁,因为当数据可用时消费者没有得到通知。任何人都可以查看代码吗?
import java.util.List;
import java.util.ArrayList;
import java.util.concurrent.locks.*;
class ThreadFactory implements Runnable{
List<String> list = new ArrayList<>();
Thread prThread;
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final int CAPACITY = 10;
public enum Role{
PRODUCER,
CONSUMER
};
Role role;
public int i = 0;
private void produce() throws InterruptedException {
while(true){
lock.lock();
try{
while(list.size() == CAPACITY){
System.out.println("List is full to its CAPACITY, waiting");
notEmpty.await();
}
String str = "Data " + i++;
System.out.println("Putting " + str + " to list");
list.add(str);
notFull.signalAll();
}
finally{
lock.unlock();
Thread.sleep(500);
}
}
}
private void consume() throws InterruptedException{
while(true){
lock.lock();
try{
while(list.size() == 0){
System.out.println("List is empty, waiting");
notFull.await();
}
String str = list.remove(list.size()-1);
System.out.println("Popping " + str + " from list");
notEmpty.signal();
}
finally{
lock.unlock();
}
}
}
public void run(){
System.out.println("Starting thread " + prThread.getName());
try{
if(role == Role.PRODUCER){
produce();
}
else if(role == Role.CONSUMER){
consume();
}
}
catch(InterruptedException e){
System.out.println("Thread interrupted");
}
}
public ThreadFactory(List<String> l, int role, String name){
this.list = l;
prThread = new Thread(this, name);
if(role == 0)
this.role = Role.PRODUCER;
else
this.role = Role.CONSUMER;
prThread.start();
}
}
public class ProducerConsumer{
public static void main(String[] args){
List<String> l = new ArrayList<>();
ThreadFactory c = new ThreadFactory(l,1, "Consumer");
ThreadFactory p = new ThreadFactory(l,0, "Producer");
}
}
好吧,我不确定发生了什么,可能是因为您正在 运行同时生产 consume() 和 produce ()方法在classThreadFactory的方法运行()中。
我要做的是为消费者创建一个 class,为生产者创建另一个,两个 class 扩展 class 线程。然后我将在它们各自的 classes.
的 运行() 中调用 consume() 和 producer()
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class ThreadFactory {
List<String> list = new ArrayList<>();
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final int CAPACITY = 10;
public int i = 0;
class Producer extends Thread {
@Override
public void run() {
try {
produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Consumer extends Thread {
@Override
public void run() {
try {
consume();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void produce() throws InterruptedException {
System.out.println("Starting thread " + Thread.currentThread().getName());
while (true) {
lock.lock();
try {
while (list.size() == CAPACITY) {
System.out.println("List is full to its CAPACITY, producer waiting");
notFull.await();
}
if (i == CAPACITY) i=0;
String str = "Data " + i++;
System.out.println("Putting " + str + " to list of size "+list.size());
list.add(str);
if (list.size() ==1 )
notEmpty.signal();
} finally {
lock.unlock();
Thread.sleep(500);
}
}
}
private void consume() throws InterruptedException {
System.out.println("Starting thread " + Thread.currentThread().getName());
while (true) {
lock.lock();
try {
while (list.size() == 0) {
System.out.println("List is empty, consumer waiting");
notEmpty.await();
}
String str = list.remove(list.size() - 1);
System.out.println("Popping " + str + " from list of size "+list.size());
if (list.size() ==CAPACITY-1 )
notFull.signal();
} finally {
lock.unlock();
}
}
}
public ThreadFactory(List<String> l ){
this.list = l;
Thread p= new Producer();
p.setName("Producer");
p.start();
Thread c=new Consumer();
c.setName("Consumer");
c.start();
}
}
public class ProducerConsumer {
public static void main(String[] args) {
List<String> l = new ArrayList<>();
ThreadFactory pc = new ThreadFactory(l);
}
}
希望对您有所帮助。
这不是死锁,锁是每个 class 的实例成员,其中每个可运行实例都创建自己的锁。你的生产者和消费者使用他们自己的锁,所以他们看不到彼此的信号,他们永远等待。他们应该使用同一把锁。
我是 Java 的新手,我正在尝试学习 Java 并发。我已经为生产者-消费者问题(单一生产者和消费者)编写了一个简单的代码。似乎存在死锁,因为当数据可用时消费者没有得到通知。任何人都可以查看代码吗?
import java.util.List;
import java.util.ArrayList;
import java.util.concurrent.locks.*;
class ThreadFactory implements Runnable{
List<String> list = new ArrayList<>();
Thread prThread;
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final int CAPACITY = 10;
public enum Role{
PRODUCER,
CONSUMER
};
Role role;
public int i = 0;
private void produce() throws InterruptedException {
while(true){
lock.lock();
try{
while(list.size() == CAPACITY){
System.out.println("List is full to its CAPACITY, waiting");
notEmpty.await();
}
String str = "Data " + i++;
System.out.println("Putting " + str + " to list");
list.add(str);
notFull.signalAll();
}
finally{
lock.unlock();
Thread.sleep(500);
}
}
}
private void consume() throws InterruptedException{
while(true){
lock.lock();
try{
while(list.size() == 0){
System.out.println("List is empty, waiting");
notFull.await();
}
String str = list.remove(list.size()-1);
System.out.println("Popping " + str + " from list");
notEmpty.signal();
}
finally{
lock.unlock();
}
}
}
public void run(){
System.out.println("Starting thread " + prThread.getName());
try{
if(role == Role.PRODUCER){
produce();
}
else if(role == Role.CONSUMER){
consume();
}
}
catch(InterruptedException e){
System.out.println("Thread interrupted");
}
}
public ThreadFactory(List<String> l, int role, String name){
this.list = l;
prThread = new Thread(this, name);
if(role == 0)
this.role = Role.PRODUCER;
else
this.role = Role.CONSUMER;
prThread.start();
}
}
public class ProducerConsumer{
public static void main(String[] args){
List<String> l = new ArrayList<>();
ThreadFactory c = new ThreadFactory(l,1, "Consumer");
ThreadFactory p = new ThreadFactory(l,0, "Producer");
}
}
好吧,我不确定发生了什么,可能是因为您正在 运行同时生产 consume() 和 produce ()方法在classThreadFactory的方法运行()中。
我要做的是为消费者创建一个 class,为生产者创建另一个,两个 class 扩展 class 线程。然后我将在它们各自的 classes.
的 运行() 中调用 consume() 和 producer()import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class ThreadFactory {
List<String> list = new ArrayList<>();
final Lock lock = new ReentrantLock();
final Condition notFull = lock.newCondition();
final Condition notEmpty = lock.newCondition();
final int CAPACITY = 10;
public int i = 0;
class Producer extends Thread {
@Override
public void run() {
try {
produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Consumer extends Thread {
@Override
public void run() {
try {
consume();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void produce() throws InterruptedException {
System.out.println("Starting thread " + Thread.currentThread().getName());
while (true) {
lock.lock();
try {
while (list.size() == CAPACITY) {
System.out.println("List is full to its CAPACITY, producer waiting");
notFull.await();
}
if (i == CAPACITY) i=0;
String str = "Data " + i++;
System.out.println("Putting " + str + " to list of size "+list.size());
list.add(str);
if (list.size() ==1 )
notEmpty.signal();
} finally {
lock.unlock();
Thread.sleep(500);
}
}
}
private void consume() throws InterruptedException {
System.out.println("Starting thread " + Thread.currentThread().getName());
while (true) {
lock.lock();
try {
while (list.size() == 0) {
System.out.println("List is empty, consumer waiting");
notEmpty.await();
}
String str = list.remove(list.size() - 1);
System.out.println("Popping " + str + " from list of size "+list.size());
if (list.size() ==CAPACITY-1 )
notFull.signal();
} finally {
lock.unlock();
}
}
}
public ThreadFactory(List<String> l ){
this.list = l;
Thread p= new Producer();
p.setName("Producer");
p.start();
Thread c=new Consumer();
c.setName("Consumer");
c.start();
}
}
public class ProducerConsumer {
public static void main(String[] args) {
List<String> l = new ArrayList<>();
ThreadFactory pc = new ThreadFactory(l);
}
}
希望对您有所帮助。
这不是死锁,锁是每个 class 的实例成员,其中每个可运行实例都创建自己的锁。你的生产者和消费者使用他们自己的锁,所以他们看不到彼此的信号,他们永远等待。他们应该使用同一把锁。