10

I have been reading alot of the other questions as well as alot of google searches and I've been unable to find a clear solution.

Based on some best practices I've read, the static methods of a class should be created thread safe, and the instance members should leave thread safety to the consumers.

I would like to implement a deep copy method for the class. The class itself has other reference type members. Is there any way to make the deep copy method thread safe without having to impose the overhead on all of the instanced members of the class?

Sait
  • 125
  • 1
  • 5

1 Answers1

1

As to the cloning, stack overflow already has a good answer.

Deep cloning objects

as for thread safety, I would imagine the only guarantee is if you put locks around your member variables during your copy.

Update:

Ok, I've done some research. I think the most elegant way to ensure the thread safety of your members is for the calling threads to hold locks on the object instead of trying to implement it inside your class. Also, implement the ICloneable interface and then you can just do a binary copy of the entire object easily. See the answer in the link I posted above. Of course, you could still implement locks for your static members inside your class easily.

Community
  • 1
  • 1
Jonathan Henson
  • 8,076
  • 3
  • 28
  • 52
  • And I have to assume the performance penalty of putting locks everywhere would be significant. – Tim May 19 '11 at 02:03
  • Well, I mean, you can put the locks around the objects themselves only inside your clone method. Then the only cost would be during the copy. – Jonathan Henson May 19 '11 at 02:05
  • But wouldn't you need locks in all your getters/setters too? – Tim May 19 '11 at 02:06
  • also, you can plan based on your member access and what can be accessed and/or mutated at any given time and probably get away with not locking some of them. It all depends on the combination of accessing and mutating together. – Jonathan Henson May 19 '11 at 02:07
  • You don't need to worry about your getter/setters if you lock the actual object that the getter/setter is encapsulating. The lock will stop the mutator/accessors from accessing the underlying data while the clone method has the semaphore. – Jonathan Henson May 19 '11 at 02:08
  • Hrm. that's not how I understood locks to work. Perhaps I should go brush up before talking about it any more :) – Tim May 19 '11 at 02:10
  • AAAAH, you are right. Hang on, I've done this before, let me see what I can dig up. – Jonathan Henson May 19 '11 at 02:11
  • The problem I'm facing is that there are approximately 30 members of this class. If I lock during the clone method, I would need to have a shared lock object. In order for that lock to have any effect, I would have to obtain a lock on that in the setters for all 30 properties. – Sait May 19 '11 at 02:12
  • Just curious, so I assume that since you are so worried about performance, that you are planning on having potentially many threads using this class. So... why wouldn't the concerned members not already have locks to begin with. Also, you only need to worry about semaphores when you have reads/writes happening simultaneously or when you need to synchronize threads. So if you design carefully, you shouldn't take that much of a hit. – Jonathan Henson May 19 '11 at 02:14
  • @Sait, the mutators could lock their underlying data individually, then the clone method could lock on each member instead of using a shared object. That should save on performance as the odds of two threads accessing the same lock simultaneously would be drastically reduced. – Jonathan Henson May 19 '11 at 02:20
  • But the clone method would need to obtain a lock on them all at the same time. If I lock each object individually, then I could get half way through the clone, and another thread could modify one property before I get a lock on that property. I admit I'm not that experienced with writing thread-safe code so I may me missing something here. – Sait May 19 '11 at 02:24
  • This is nasty but you could nest your locks so that you don't begin work until you have grabbed each individual lock; but by the time you have gone to that trouble, you might as well have done a shared lock. – Jonathan Henson May 19 '11 at 03:28
  • I have gotten many design ideas from the way PTLib handles threads. Maybe look at their PThread and PWaitAndSignal classes. I find their designs to be quite brilliant. – Jonathan Henson May 19 '11 at 03:30
  • Yea, I thought the same about the nested locks also. I'll check out those examples. Otherwise i'll fall back to just doing shared locks. The performance on this project won't hurt, but it was more of "do it right the first time" kinda thing. Accepted answer for all the helpful advice. – Sait May 19 '11 at 03:45
  • Thanks. Seriously, I thought I was a good architect until I saw PTLib. It blew my mind. – Jonathan Henson May 19 '11 at 04:49
  • Probably not one of the best solutions. I implemented a Syncronized property to return a wrapper with the locks in place. Guess I should have looked at what the framework designers implemented before trying to reinvent the wheel. – Sait May 22 '11 at 05:50
  • do a post on it as I want to know how to do it as well. – Jonathan Henson May 23 '11 at 02:12