public class Data
{
//存放消息的hash表
private static Map<Long,Message> messageList = new HashMap<Long, Message>();
//互斥访问量
public static final Semaphore read = new Semaphore(1);
public static final Semaphore write = new Semaphore(1);
public static int readerCount = 0;
private static final Data data = new Data();//单例
private Data()
{
}
public static Data getInstance()
{
return data;
}
//添加一个消息到消息表中
public void addMessage(Message msg)
{
Long key = msg.getId();
writeAcquire();
messageList.put(key, msg);
writeRelease();
}
//移除某个消息
public void removeMessage(Long key)
{
writeAcquire();
messageList.remove(key);
writeRelease();
}
/*
*还有很多方法,这里省略
*/
//读者信号加锁
public void readAcquire()
{
try
{
read.acquire();
readerCount++;
if(readerCount == 1)
{
write.acquire();
}
read.release();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
//写者信号加锁
public void writeAcquire()
{
try
{
write.acquire();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
//读者信号解锁
public void readRelease()
{
try
{
read.acquire();
readerCount--;
if(readerCount == 0)
{
write.release();
}
read.release();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
//写者信号解锁
public void writeRelease()
{
write.release();
}
}
但是这样会死锁,短则一两分钟,多则10来分钟,线程就全部卡死了。多线程的调试实在是让人崩溃,大牛们看看问题在哪。
5 个解决方案
#1
好像是出错在这儿:public void readAcquire()
{
try
{
read.acquire();
readerCount++;
if(readerCount == 1)
{
write.acquire();
}
read.release();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
write.acquire();没有释放信号量啊,这一段还有其他的错误。写者write就始终申请不到呀!
另外读者的初始信号量应设置成多给人进去读,还有就是这个acquier(),和release()方法要某一个出现的后面配对样。
{
try
{
read.acquire();
readerCount++;
if(readerCount == 1)
{
write.acquire();
}
read.release();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
write.acquire();没有释放信号量啊,这一段还有其他的错误。写者write就始终申请不到呀!
另外读者的初始信号量应设置成多给人进去读,还有就是这个acquier(),和release()方法要某一个出现的后面配对样。
#2
你的测试代码是什么?
#3
建议使用 ReentrantReadWriteLock,有现成的读写锁为啥不用?
如果要自己实现一个读写锁的话是很麻烦的。
如果要自己实现一个读写锁的话是很麻烦的。
#4
写者信号的解锁是在readerRelease函数里,当读者退出时会调用readerRelease函数。
#5
测试代码就是一些线程不断的对data类里的messageList进行操作,读或写。如Data.getInstance.addMessage Data.getInstance.removeMessage或getMessage。线程内部没有互斥访问的代码,互斥访问的代码嵌在data的各个方法里。
#1
好像是出错在这儿:public void readAcquire()
{
try
{
read.acquire();
readerCount++;
if(readerCount == 1)
{
write.acquire();
}
read.release();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
write.acquire();没有释放信号量啊,这一段还有其他的错误。写者write就始终申请不到呀!
另外读者的初始信号量应设置成多给人进去读,还有就是这个acquier(),和release()方法要某一个出现的后面配对样。
{
try
{
read.acquire();
readerCount++;
if(readerCount == 1)
{
write.acquire();
}
read.release();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
write.acquire();没有释放信号量啊,这一段还有其他的错误。写者write就始终申请不到呀!
另外读者的初始信号量应设置成多给人进去读,还有就是这个acquier(),和release()方法要某一个出现的后面配对样。
#2
你的测试代码是什么?
#3
建议使用 ReentrantReadWriteLock,有现成的读写锁为啥不用?
如果要自己实现一个读写锁的话是很麻烦的。
如果要自己实现一个读写锁的话是很麻烦的。
#4
写者信号的解锁是在readerRelease函数里,当读者退出时会调用readerRelease函数。
#5
测试代码就是一些线程不断的对data类里的messageList进行操作,读或写。如Data.getInstance.addMessage Data.getInstance.removeMessage或getMessage。线程内部没有互斥访问的代码,互斥访问的代码嵌在data的各个方法里。