473,703 Members | 3,307 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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 1713
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.Collecti on 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(someotherR efType){} ?
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.Collecti on 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.Collecti on 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(someotherR efType){} ?
easy; any thread that needs your collection (even if they are only
iterating it) needs to do this:

// myCollection is a
System.Collecti ons.Generic.Lis t<System.Drawin g.Point>, just for
example..
lock( myCollection.Sy ncRoot ) {
// 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(someotherR efType){} ?
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.Collecti on 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.r it.eduschrieb im Newsbeitrag
news:11******** **************@ i3g2000cwc.goog legroups.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(someother RefType){} ?

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

// myCollection is a
System.Collecti ons.Generic.Lis t<System.Drawin g.Point>, just for
example..
lock( myCollection.Sy ncRoot ) {
// 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 ChangesFooAsync hronously()
{
// 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.ChangeMeAg ain();

// 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(someotherR efType){} ?

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.Collecti on 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 ChangesFooAsync hronously()
{
// 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.ChangeMeAg ain();

// 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 DoSomethingThat StartsThread()
{
// Copy the data structure.
lock (lockObject)
{
// This must be a deep copy.
fooCopy = foo.Clone();
}

// Start ChangeFooAsynch ronously in another thread.
}

private void ChangeFooAsynch ronously()
{
// We can safely access the copied data structure here.
fooCopy.ChangeM e();
fooCopy.ChangeM eAgain();

// 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
2029
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 good.. not there in VB.net?? 2. Some language features of VB.Net like Redim(makes it easier for developers), but not good enough reason. 3. C# is in more like standard languages and key words used are more
3
1559
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 Monitor.PulseAll(myList.SyncRoot); }
385
17189
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 extraneous jargons, such as in the Unix & Perl community. Unlike mathematicians, where in mathematics there are no fewer jargons but each and every one are
14
2154
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 necessary that the object allocated in each generation and the generations themselves be in the form of contigious memory locations.
18
3069
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, when memory becomes limited, the garbage collector is moved up in priority. I believe they must be overly simplified explanations because I would tend to guess that Microsoft would have allowed for more pre-emptive reclaiming of memory to best...
11
2166
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 possible to extend the Singleton pattern to handle this? Assuming that my Customer class follows the Singleton pattern (particularly Skeet's 4th version) I'm thinking if I add private static SomeCollectionType customers;
8
12929
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 that the object will not be garbage collected while the thread is running. Fair enough, the documented explanation is that the GC compresses objects on the heap and needs to update references, the references will be invalid for a couple of moments...
18
2205
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 documents that you could point me to help me control the GC, then that would be great also. The .Net GC does not cleanup memory of our service process unless it is forced to by another process that hogs memory. · GC Algorithm - This is an issue...
158
7812
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 discouraged due to some specific reason. If someone can give inputs on the same, it will be of great help. Regards, Pushpa
0
8662
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9243
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9109
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9002
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
7853
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6585
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4677
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3113
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
2434
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.