To use shared members or not

Posts   
 
    
Devildog74
User
Posts: 719
Joined: 04-Feb-2004
# Posted on: 02-Jun-2004 05:54:16   

The comments below are my thoughts on threading and shared members. I think I have a pretty good understanding of shared members and thread safety. I am looking for feedback from the community as to whether or not my thoughts are valid.

Basically, to be thread safe means that the data being acted upon will only be effected by the current unit of work, i.e. the current thread. All other threads will be blocked from accessing the particular bit of code/memory until the current thread is done with it.

I also beleive that I read somewhere that data access adapers are not thread safe. I also read the following in the reference manual: "Use a DataAccessAdapter object solely per thread, and per connection. A DataAccessAdapter object contains 1 active connection and no thread-access scheduling code. This means that you need to create a new DataAccessAdapter object if you want to utilize in another thread a new connection and a new transaction or want to open a new connection."

After reading the statement above, I think it means that you **DO NOT **want to write code like this:


public class MyDB
private mDB as DataAccessAdapter

public sub new
  mDB = New DataAccessAdapter(true)
end sub

public property Connection as DataAccessAdapter
 get 
   return mDB
 set
   mDB = value
end property

end class


public class MyClientForm
  dim myData as new MyDB
  dim ent as new EmployeeEntity
  ent.FirstName = Bob
  myData.Connection.SaveEntity(ent)
end class

So what does this have to do with shared members? Well, it's my understanting that every .net type has a native interface. This is the basic definition of the class itself. Shared members are automatically available in memory without having an to create a specific instance of the type. I beleive that this is acheivable due to the native interface of the type.

One question is, since you will never have an instance specific object alive in a shared member, can you always assume that objects accessed in a shared member are thread safe and that shared members are thread safe?

For example, if I write a shared method like so:


shared sub SaveEntity(ent as IEntity2)
  dim db as new DataAccessAdapter(false)
  db.SaveEntity(ent)
end sub

and this method is hosted in a remote, server activated, single call object. Can client A and client B can call the saveEntity method safely at the same time without worring about mixing up the data?

Another thing that I find baffling about shared members is this. If I dont need to store statefule information in the BAL, and all members are service based, can all the members be shared?

Sometimes, object creation can take a long time, (i.e. it can take length of time to create an instance of an object like a connection), therefore you might want to put these objects into a thread pool, because after all, why waste time creating them, when you can have a pool of them ready to do your bidding. That being said, what are the implications of pooling an object with only shared members?

So the real basis for the question is, I cannot figure out what the best practices are for using shared members or not to. I have also been asked by my co-workers as to why we should or should not use shared members. Any insight into this would be appreciated.

jeffreygg
User
Posts: 805
Joined: 26-Oct-2003
# Posted on: 02-Jun-2004 21:28:05   

Please keep in my mind as you are reading my responses, that I have no business being here simple_smile Maybe I can just be a sounding board since no one else has responded.

Devildog74 wrote:

The comments below are my thoughts on threading and shared members. I think I have a pretty good understanding of shared members and thread safety. I am looking for feedback from the community as to whether or not my thoughts are valid.

Basically, to be thread safe means that the data being acted upon will only be effected by the current unit of work, i.e. the current thread. All other threads will be blocked from accessing the particular bit of code/memory until the current thread is done with it.

I also beleive that I read somewhere that data access adapers are not thread safe. I also read the following in the reference manual: "Use a DataAccessAdapter object solely per thread, and per connection. A DataAccessAdapter object contains 1 active connection and no thread-access scheduling code. This means that you need to create a new DataAccessAdapter object if you want to utilize in another thread a new connection and a new transaction or want to open a new connection."

After reading the statement above, I think it means that you **DO NOT **want to write code like this:


public class MyDB
private mDB as DataAccessAdapter

public sub new
  mDB = New DataAccessAdapter(true)
end sub

public property Connection as DataAccessAdapter
 get 
   return mDB
 set
   mDB = value
end property

end class


public class MyClientForm
  dim myData as new MyDB
  dim ent as new EmployeeEntity
  ent.FirstName = Bob
  myData.Connection.SaveEntity(ent)
end class

According to your above definition, the above would be sufficient as long as you initialized a new MyDB for each call, right? Basically, 1 thread per each instance.

So what does this have to do with shared members? Well, it's my understanting that every .net type has a native interface. This is the basic definition of the class itself. Shared members are automatically available in memory without having an to create a specific instance of the type. I beleive that this is acheivable due to the native interface of the type.

One question is, since you will never have an instance specific object alive in a shared member, can you always assume that objects accessed in a shared member are thread safe and that shared members are thread safe?

For example, if I write a shared method like so:


shared sub SaveEntity(ent as IEntity2)
  dim db as new DataAccessAdapter(false)
  db.SaveEntity(ent)
end sub

and this method is hosted in a remote, server activated, single call object. Can client A and client B can call the saveEntity method safely at the same time without worring about mixing up the data?

I would assume again, based on the above definition, that since there is only one instance alive in memory we are doing 1 instance for many threads <> good. The only alternative to that answer I can think of is if the object blocks per call till the last operation is complete.

Another thing that I find baffling about shared members is this. If I dont need to store statefule information in the BAL, and all members are service based, can all the members be shared?

I've thought about that question as well. Seems to me services should be set as shared as long as they aren't stateful. Thus, if the object does not contain any stateful services, then all the members should be shared.

Jeff...

Devildog74
User
Posts: 719
Joined: 04-Feb-2004
# Posted on: 02-Jun-2004 21:39:52   

jeffreygg wrote:

Maybe I can just be a sounding board since no one else has responded.

Thanks for the sanity check.

Devildog74
User
Posts: 719
Joined: 04-Feb-2004
# Posted on: 04-Jun-2004 03:09:13   

Any other takers? Otis, Wayne, or Bert anyone?

bertcord avatar
bertcord
User
Posts: 206
Joined: 01-Dec-2003
# Posted on: 04-Jun-2004 14:50:27   

Hey devildog...

I was a littel confused disappointed

Your first code block is a non shared class and you say "DO NOT" write code like this?

IS this wahy you ment? If not why not qrite code like this? Each MyDB instance creates a new dataaccessadapter class correct?

Bert

Devildog74
User
Posts: 719
Joined: 04-Feb-2004
# Posted on: 04-Jun-2004 15:44:24   

bertcord wrote:

Hey devildog...

I was a littel confused disappointed

Your first code block is a non shared class and you say "DO NOT" write code like this?

IS this wahy you ment? If not why not qrite code like this? Each MyDB instance creates a new dataaccessadapter class correct?

Bert

Jeff pointed out that my first code block should work fine as long as I was always working with a new Instance of MyDB on the client side. I just never edited the post. So the first code block could be thread safe. I guess maybee I was looking for an example that would introduce potential threading problems.

I think if Client A creates an instance of MyDB and passes this instance to WorkerThread A and WorkerThread B, this would be bad practice because you would have 2 threads trying to access the same reference type, e.g the reference pointer to the instance of MyDB created in the main thread. So I think you could say that the first code sample could get you into trouble.

MarcoP avatar
MarcoP
User
Posts: 270
Joined: 29-Sep-2004
# Posted on: 31-Oct-2004 05:48:09   

In your example, this is definetly not thread safe. Whenever your class contains shared or class-level members, without any locking, you're exposing yourself to threading issues. The reason for this is because these resources are not pushed onto the stack, thus each thread is dealing with the same resource.