In my Application I have various threads reading
data from collections. Say, there are 20 readers. One Thread is responsible for periodically refreshing that collection with new data.
Now, using the lock
statement from within all threads (reader and writer) will have the drawback, that the readers block each other as well. Simplified Example:
private readonly object lockObj = new Object();
private List<String>() data;
public void dataReader1(){
lock(lockObj){
//read...
}
}
public void dataReader2(){
lock(lockObj){
//read...
}
}
public void dataReader3(){
lock(lockObj){
//read...
}
}
public void dataWriter(){
lock(lockObj){
//write write write...
}
}
Obviously now only one reader can access the data at the time.
To overcome this issue, I could use a global writeLock and different read lock objects like this:
private List<String>() data;
private readonly object writeLock = new Object();
private readonly object readLock1 = new Object();
private readonly object readLock2 = new Object();
private readonly object readLock3 = new Object();
public void dataReader1(){
lock(readLock1){
//read...
}
}
public void dataReader2(){
lock(readLock2){
//read...
}
}
public void dataReader3(){
lock(readLock3){
//read...
}
}
public void dataWriter(){
lock(readLock1){
lock(readLock2){
lock(readLock3){
lock(writeLock){
//write write write...
}
}
}
}
}
Now, every thread can read - until the writer starts to lock them out, till he finally got the exclusive write Lock.
I don't really like this approach, because nesting locks smells like dead-lock incoming sooner or later. So, I wonder if there is a native way to achieve this with a single lock statement?
Thinking of something like ...
private readonly object lockObj= new Object();
private List<String>() data;
public void dataReader1(){
readonly lock(lockObj){
//read...
}
}
public void dataReader2(){
readonly lock(lockObj){
//read...
}
}
public void dataReader3(){
readonly lock(lockObj){
//read...
}
}
public void dataWriter(){
lock(lockObj){
//write write write...
}
}
... where C# is able to understand, that readonly lock
can be entered, unless there is a lock
in place (or trying to be aquired) - and that lock
in turn is waiting, until there is no more existing readonly lock
.