Designing thread safety

Java language and API supports multi-threading, so let's discuss briefly the key points, we should consider designing thread safe.
Why do we need thread-safe? 
Well, because multithreading is built into Java, it is possible that any class you design eventually may be used concurrently by multiple threads. You needn't (and shouldn't) make every class you design thread-safe, because thread safety doesn't come for free. But you should at least think about thread safety every time you design a Java class.
Given the architecture of the JVM, you need only be concerned with instance and class variables when you worry about thread safety. Because all threads share the same heap, and the heap is where all instance variables are stored, multiple threads can attempt to use the same object's instance variables concurrently. Likewise, because all threads share the same method area, and the method area is where all class variables are stored, multiple threads can attempt to use the same class variables concurrently. When you do choose to make a class thread-safe, your goal is to guarantee the integrity -- in a multithreaded environment -- of instance and class variables declared in that class.
You needn't worry about multithreaded access to local variables, method parameters, and return values, because these variables reside on the Java stack. In the JVM, each thread is awarded its own Java stack. No thread can see or use any local variables, return values, or parameters belonging to another thread.
Given the structure of the JVM, local variables, method parameters, and return values are inherently "thread-safe." But instance variables and class variables will only be thread-safe if you design your class appropriately.
How to make an object thread-safe?
There are basically three approaches you can take to make an object thread-safe:
Synchronize critical sections: For this approach is essential to make all fields that you need to coordinate multithreaded access to, private. (only the fields involved in any temporarily invalid states). Otherwise it may be possible for other classes and objects to ignore your critical sections and access the fields directly. Then, you need to mark the object's critical sections as synchronized. A critical section is a bit of code that must be executed atomically, that is, as a single, indivisible operation. (use the Syncronized modifier).
Make it immutable: An immutable object is one whose state can't be changed once the object is created.Immutable objects are, by their very nature, thread-safe simply because threads have to be able to write to an object's instance variables to experience a read/write or write/write conflict. Because no methods (only the constructor) of an immutable object actually write to the object's instance variables, the object is by definition thread-safe.In this approach to making an object thread-safe, you don't mark critical sections as synchronized. Instead, you separate out the critical sections that read instance variables from those that write to instance variables. The critical sections that read are left as-is. The critical sections that write must be changed so that, instead of altering the current object's instance variables, they create a new object that embodies the new state and returns a reference to that object.
Use a thread-safe wrapper: The third approach to making an object thread-safe is to embed that object in a thread-safe wrapper object. In this approach you leave the original class (which isn't thread-safe) unchanged and create a separate class that is thread-safe. Instances of the new class serve as thread-safe "front ends" to instances of the original class.
Why not just synchronize everything?
thread safety may involve a performance penalty. For example:
Synchronized method invocations generally are going to be slower than non-synchronized method invocations. In Sun's current JVM, for example, synchronized method invocations are 4 to 6 times slower than non-synchronized method invocations.
Unnecessary synchronized method invocations (and synchronized blocks) can cause unnecessary blocking and unblocking of threads, which can hurt performance.
Synchronization gives rise to the possibility of deadlock, a severe performance problem in which your program appears to hang.
Using immutable objects,
Achieving thread safety by making objects immutable (Approach 2) works well when objects are small and represent values of a simple abstract data type. The Java API includes several examples of immutable objects, including String and the primitive type wrappers such as Integer, Long, Float, Boolean, Character, and so on. If the overhead of immutability (excessive creation of short-lived objects) may at times be too inefficient, you can define a mutable companion class that can be used when the immutable version isn't appropriate.
Using wrapper objects?
The wrapper object approach to thread safety makes the most sense when you want to give clients a choice between a version of a class that is thread-safe and one that isn't. This approach also makes sense when you're a client of someone else's class that isn't thread-safe, but you need to use the class in a multithreaded environment. Once you define your own thread-safe wrapper for the class, you can safely use the class in a multithreaded environment by going through your wrapper.
When to make classes thread-safe?
Your thread-safety decision should be based simply on whether or not your class will be exposed to potential write/write or read/write conflicts by your programs. To know whether or not such conflicts are possible, you just have to know how your program will work.
If, instead of creating classes for an applet or application, you are creating classes for a library, either one that will be shared in-house or will serve as a product in its own right, you have a different problem. You may not know exactly how the classes will be used. In such cases, it may be a good idea to give clients a choice via the thread-safe wrapper approach.
Resources
Resources and discussion forum.

Comentarios