473,396 Members | 1,724 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

how to prohibit writing to a collection by other threads ?

Does anyone have a simple example on how to prohibit that any thread
other than the current thread modifies a certain object (a collection)
while we are in a certain section of the code?
In other words: while we are inside this codeblock whoever might think
of modified that particular collection has to wait until we have left
that codeblock.

As far as I understand it lock() {} only prohibits that other threads
enter a certain block of code while the current thread is inside of it
but does not prohibit modification of the object that was passed as the
parameter for lock() ...

Sep 7 '06 #1
9 1700
I belive this is why your collection instance has a SyncRoot property;
all your threads should lock on that object before attempting to modify
the contents of the collection.

HTH
Andy

bonk wrote:
Does anyone have a simple example on how to prohibit that any thread
other than the current thread modifies a certain object (a collection)
while we are in a certain section of the code?
In other words: while we are inside this codeblock whoever might think
of modified that particular collection has to wait until we have left
that codeblock.

As far as I understand it lock() {} only prohibits that other threads
enter a certain block of code while the current thread is inside of it
but does not prohibit modification of the object that was passed as the
parameter for lock() ...
Sep 7 '06 #2

bonk wrote:
Does anyone have a simple example on how to prohibit that any thread
other than the current thread modifies a certain object (a collection)
while we are in a certain section of the code?
In other words: while we are inside this codeblock whoever might think
of modified that particular collection has to wait until we have left
that codeblock.

As far as I understand it lock() {} only prohibits that other threads
enter a certain block of code while the current thread is inside of it
but does not prohibit modification of the object that was passed as the
parameter for lock() ...
That's correct. The lock keyword will not prevent modification or even
access to the object used in that statement. What it prevents is a
thread from entering a critical section (that's the code block wrapped
by the lock) if another thread has already entered a critical section
guarded by the same object. So what you need to do is make sure that
all modifications to your collection are guarded by the same object.
If you're using a collection from the System.Collection namespace then
the SyncRoot property of the collection is the ideal candidate for the
guard object, but depending on exactly what you're after and what
specific collection you're using you may choose a different object.

Brian

Sep 7 '06 #3
That's correct. The lock keyword will not prevent modification or even
access to the object used in that statement. What it prevents is a
thread from entering a critical section (that's the code block wrapped
by the lock) if another thread has already entered a critical section
guarded by the same object.
But what is the Paramter for the lock() statement for then? To prohibit
other threads form entering a certain codeblock I wouldn't need some
strange other object. What does it mean to "obtain at mutual-exclusion
lock for a given object"? How does doing a lock(this){} differ from a
lock(someotherRefType){} ?
So what you need to do is make sure that
all modifications to your collection are guarded by the same object.
If you're using a collection from the System.Collection namespace then
the SyncRoot property of the collection is the ideal candidate for the
guard object, but depending on exactly what you're after and what
specific collection you're using you may choose a different object.
The situation is this: A method does a lengthy operation on the
collection (iterating over it an modifiing it and its content) while
this method is running no other object that might have a refernce to
that collection and no other thread else is allowed to modify that
collection.

Brian Gideon schrieb:
bonk wrote:
Does anyone have a simple example on how to prohibit that any thread
other than the current thread modifies a certain object (a collection)
while we are in a certain section of the code?
In other words: while we are inside this codeblock whoever might think
of modified that particular collection has to wait until we have left
that codeblock.

As far as I understand it lock() {} only prohibits that other threads
enter a certain block of code while the current thread is inside of it
but does not prohibit modification of the object that was passed as the
parameter for lock() ...

That's correct. The lock keyword will not prevent modification or even
access to the object used in that statement. What it prevents is a
thread from entering a critical section (that's the code block wrapped
by the lock) if another thread has already entered a critical section
guarded by the same object. So what you need to do is make sure that
all modifications to your collection are guarded by the same object.
If you're using a collection from the System.Collection namespace then
the SyncRoot property of the collection is the ideal candidate for the
guard object, but depending on exactly what you're after and what
specific collection you're using you may choose a different object.

Brian
Sep 8 '06 #4

bonk wrote:
But what is the Paramter for the lock() statement for then? To prohibit
other threads form entering a certain codeblock I wouldn't need some
strange other object. What does it mean to "obtain at mutual-exclusion
lock for a given object"? How does doing a lock(this){} differ from a
lock(someotherRefType){} ?
easy; any thread that needs your collection (even if they are only
iterating it) needs to do this:

// myCollection is a
System.Collections.Generic.List<System.Drawing.Poi nt>, just for
example..
lock( myCollection.SyncRoot ) {
// Do list stuff here
}

That will keep your access to the collection thread safe.

Sep 8 '06 #5
bonk wrote:
That's correct. The lock keyword will not prevent modification or even
access to the object used in that statement. What it prevents is a
thread from entering a critical section (that's the code block wrapped
by the lock) if another thread has already entered a critical section
guarded by the same object.

But what is the Paramter for the lock() statement for then? To prohibit
other threads form entering a certain codeblock I wouldn't need some
strange other object.
Every object can have a monitor associated with it. The lock statement
automatically generates the calls to Monitor.Enter and Monitor.Exit at
compile time. When Monitor.Enter is called the monitor associated with
the object parameter is acquired if it's not currently "held" or the
call blocks until it can be acquired. When Monitor.Exit is called the
monitor is released allowing other threads the chance to acquire it.
So the lock isn't protecting the object parameter at all. Instead, the
object parameter is the how Monitor class uniquely identifies a
monitor.
What does it mean to "obtain at mutual-exclusion lock for a given
object"?
I see how that statement is confusing. It does not mean that access to
the object itself is constrained or "locked". It just means that the
object is used to constrain or "lock" execution of a code block. The
object is only used to help identify the lock.
How does doing a lock(this){} differ from a
lock(someotherRefType){} ?
They're using different objects so they would be associated with
different monitors. In other words, the locks are unrelated and
operate independently of each other.
So what you need to do is make sure that
all modifications to your collection are guarded by the same object.
If you're using a collection from the System.Collection namespace then
the SyncRoot property of the collection is the ideal candidate for the
guard object, but depending on exactly what you're after and what
specific collection you're using you may choose a different object.

The situation is this: A method does a lengthy operation on the
collection (iterating over it an modifiing it and its content) while
this method is running no other object that might have a refernce to
that collection and no other thread else is allowed to modify that
collection.
Anytime you access the collection make sure it is guarded by locks
using the *same* object. In the case of an ICollection the SyncRoot
property provides a good choice, but you're free to use another object
and it would still be safe.

Sep 8 '06 #6
Consider the following scenario: I am writing an API for others to use. It
has some public classes that expose some some fields as public (via property
acessors) or as protected (as fields directly) and they therefore can be
freely acessed by the user of my class (either by instanciating or deriving
from that class). Now inside some internal methods of these public classes
of my API I have to work with those fields using threads over a longer time.
So my goal is now to prohibt access to those public or protected fields
while one of my internal threads is doing some work with them. The problem
here:

The users of my class can not and should not have to know that they have to
aquire a lock to some sort of objects if they want to read or write from/to
those fields. I would like to abstact that away from the API view. Rather I
would like my API users automatically (whether they spawned their own thread
or wether they are on the main thread) to be forced to wait until my thread
is done and access is allowed again.

Hope that makes sense ...

"Andy" <aj*****@alum.rit.eduschrieb im Newsbeitrag
news:11**********************@i3g2000cwc.googlegro ups.com...
>
bonk wrote:
>But what is the Paramter for the lock() statement for then? To prohibit
other threads form entering a certain codeblock I wouldn't need some
strange other object. What does it mean to "obtain at mutual-exclusion
lock for a given object"? How does doing a lock(this){} differ from a
lock(someotherRefType){} ?

easy; any thread that needs your collection (even if they are only
iterating it) needs to do this:

// myCollection is a
System.Collections.Generic.List<System.Drawing.Poi nt>, just for
example..
lock( myCollection.SyncRoot ) {
// Do list stuff here
}

That will keep your access to the collection thread safe.

Sep 8 '06 #7
Yes, that makes more sense. Here's the deal and a few things to
consider...

Usually you want to avoid making instance members of your public
classes thread-safe. That's because some users of your library may not
be using it in a multithreaded environment and those that do will have
to enforce their on synchronization on your classes. That makes your
job easier. That's how most of the .NET base class library is
designed.

Of course that doesn't help with your library's own internal
thread-safety requirements. And you're right. Users of your library
shouldn't have to worry or even know that it is using other threads
behind the scenes whether or not you decide to make the public
interface thread-safe or not.

One strategy for dealing with this is to make your objects immutable.
The only way your threads can modify data is if they create new copies
of it. Once they have completed whatever lengthy calculation was
required to create the new data the public references would be swapped
out (in a thread-safe manner of course). Do you see how that
eliminates a lot of the complexity? The string data type in .NET,
although a reference type, is immutable. That's why it is inherently
safe to access and modify it from multiple threads.

Another strategy that might work for you is to copy any data structures
the threads will use before you kick them off. That way the threads
will be working with private copies while the original public copies
are still valid. After the threads finish their work swap the public
references out (again, in a thread-safe manner) to publish the new
data.

Both approaches have a similar theme. That is they both work by making
sure the public data structures and the data structures the threads are
working with are separate. That requires less synchronization which
makes things easier for you. They both have a similar caveat though.
How do callers of your library know when the data structures have been
updated? How much extra work is required to repeatedly make separate
copies and publish the updates? Would these strategies have unexpected
side effects to the callers of your library? You'll need to have
answers to those questions.

public class Example
{
private SomeObject foo = new SomeObject();
private Object lockObject = new Object();

public SomeObject Foo
{
get
{
lock (lockObject)
{
return foo;
}
}
}

// This method might be invoked by another thread.
private void ChangesFooAsynchronously()
{
// Copy the data structure.
SomeObject copy;
lock (lockObject)
{
// This must be a deep copy.
copy = foo.Clone();
}

// We can safely access the copied data structure here.
copy.ChangeMe();
copy.ChangeMeAgain();

// Now publish the result.
lock (lockObject)
{
foo = copy;
}
}

}

Brian

bonk wrote:
Consider the following scenario: I am writing an API for others to use. It
has some public classes that expose some some fields as public (via property
acessors) or as protected (as fields directly) and they therefore can be
freely acessed by the user of my class (either by instanciating or deriving
from that class). Now inside some internal methods of these public classes
of my API I have to work with those fields using threads over a longer time.
So my goal is now to prohibt access to those public or protected fields
while one of my internal threads is doing some work with them. The problem
here:

The users of my class can not and should not have to know that they have to
aquire a lock to some sort of objects if they want to read or write from/to
those fields. I would like to abstact that away from the API view. Rather I
would like my API users automatically (whether they spawned their own thread
or wether they are on the main thread) to be forced to wait until my thread
is done and access is allowed again.

Hope that makes sense ...
Sep 8 '06 #8
Brian, thank you for your detailed answers. You have been great help in
understanding all this. It all makes perfect sense now. And I know
where to go from here.
Brian Gideon schrieb:
bonk wrote:
That's correct. The lock keyword will not prevent modification or even
access to the object used in that statement. What it prevents is a
thread from entering a critical section (that's the code block wrapped
by the lock) if another thread has already entered a critical section
guarded by the same object.
But what is the Paramter for the lock() statement for then? To prohibit
other threads form entering a certain codeblock I wouldn't need some
strange other object.

Every object can have a monitor associated with it. The lock statement
automatically generates the calls to Monitor.Enter and Monitor.Exit at
compile time. When Monitor.Enter is called the monitor associated with
the object parameter is acquired if it's not currently "held" or the
call blocks until it can be acquired. When Monitor.Exit is called the
monitor is released allowing other threads the chance to acquire it.
So the lock isn't protecting the object parameter at all. Instead, the
object parameter is the how Monitor class uniquely identifies a
monitor.
What does it mean to "obtain at mutual-exclusion lock for a given
object"?

I see how that statement is confusing. It does not mean that access to
the object itself is constrained or "locked". It just means that the
object is used to constrain or "lock" execution of a code block. The
object is only used to help identify the lock.
How does doing a lock(this){} differ from a
lock(someotherRefType){} ?

They're using different objects so they would be associated with
different monitors. In other words, the locks are unrelated and
operate independently of each other.
So what you need to do is make sure that
all modifications to your collection are guarded by the same object.
If you're using a collection from the System.Collection namespace then
the SyncRoot property of the collection is the ideal candidate for the
guard object, but depending on exactly what you're after and what
specific collection you're using you may choose a different object.
The situation is this: A method does a lengthy operation on the
collection (iterating over it an modifiing it and its content) while
this method is running no other object that might have a refernce to
that collection and no other thread else is allowed to modify that
collection.

Anytime you access the collection make sure it is guarded by locks
using the *same* object. In the case of an ICollection the SyncRoot
property provides a good choice, but you're free to use another object
and it would still be safe.
Sep 11 '06 #9

Brian Gideon wrote:
public class Example
{
private SomeObject foo = new SomeObject();
private Object lockObject = new Object();

public SomeObject Foo
{
get
{
lock (lockObject)
{
return foo;
}
}
}

// This method might be invoked by another thread.
private void ChangesFooAsynchronously()
{
// Copy the data structure.
SomeObject copy;
lock (lockObject)
{
// This must be a deep copy.
copy = foo.Clone();
}

// We can safely access the copied data structure here.
copy.ChangeMe();
copy.ChangeMeAgain();

// Now publish the result.
lock (lockObject)
{
foo = copy;
}
}

}
There is an error in my example. As written it wouldn't be safe at
all. It should have looked like this. The copy must be done on the
caller's thread.

public class Example
{
private SomeObject foo = new SomeObject();
private SomeObject fooCopy = null;
private Object lockObject = new Object();

public SomeObject Foo
{
get
{
lock (lockObject)
{
return foo;
}
}
}

public void DoSomethingThatStartsThread()
{
// Copy the data structure.
lock (lockObject)
{
// This must be a deep copy.
fooCopy = foo.Clone();
}

// Start ChangeFooAsynchronously in another thread.
}

private void ChangeFooAsynchronously()
{
// We can safely access the copied data structure here.
fooCopy.ChangeMe();
fooCopy.ChangeMeAgain();

// Now publish the result.
lock (lockObject)
{
foo = fooCopy;
}
}

}

Sep 11 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
by: KN | last post by:
I know both are pretty much the same and it comes down to personal choice. But I have to make the choice for the team. Things so far that I am considering 1. XML documentation in C# -- thats...
3
by: wesley | last post by:
Hi List, I have a question on collection synchronisation. For example I have an ArrayList called myList and the code is like this: lock (myList.SyncRoot) { // do update on myList...
385
by: Xah Lee | last post by:
Jargons of Info Tech industry (A Love of Jargons) Xah Lee, 2002 Feb People in the computing field like to spur the use of spurious jargons. The less educated they are, the more they like...
14
by: Arvind | last post by:
hello ppl, i am trying to implement a garbage collector for c++ using the generational algorithm applying mark-sweep to each generation. i am unable to get any details about the algorithm. is it...
18
by: Rein Petersen | last post by:
Is there any way to adjust thread priority for the garbage collector? Would be nice if I could tune the thread priority rules for the garbage collector too... From my readings of the process,...
11
by: Daniel Billingsley | last post by:
Let's say I'm writing a business app and I want there to be only one instance of the Customer object for each particular customer (representing a database record) being edited. Would it be...
8
by: Martin Maat | last post by:
I am puzzled. I have this object that uses a thread. The thread is encapsulated by the object, the object has Start and Stop methods to enable the client to start or stop the thread. I found...
18
by: Larry Herbinaux | last post by:
I'm having issues with garbage collection with my long-standing service process. If you could review and point me in the right direction it would be of great help. If there are any helpful...
158
by: pushpakulkar | last post by:
Hi all, Is garbage collection possible in C++. It doesn't come as part of language support. Is there any specific reason for the same due to the way the language is designed. Or it is...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.