Java avoids race condition WITHOUT synchronization / blocking

To avoid race conditions, we can synchronize the recording and access methods for shared variables to block these variables for other threads.

My question is: are there any other (better) ways to avoid the race condition? Blocking makes the program slow.

I found:

  • using Atomic classes if there is only one common variable.
  • using an immutable container for several common variables and declare this container object unstable. (I found this method from the book "Java Concurrency in Practice")

I'm not sure if they work faster than the synchronized way, are there any other better methods?

thanks

+4
source share
5 answers

Atoms are indeed more efficient than classic locks due to their non-blocking behavior, i.e. a thread waiting for memory access will not be switched to context, which saves a lot of time.

Probably the best reference when synchronizing is to see how you can minimize the size of the critical section. Common ideas include:

  • Use read and write locks instead of full locks when you need to write only part of the threads.
  • Find ways to restructure your code to reduce the size of critical sections.
  • Use atomatics when updating a single variable.
  • Please note that some algorithms and data structures that traditionally need locks have loose versions (however, they are more complicated).
+2
source

Avoid the condition. Make your expression as stateless as possible. Each thread (sequence of actions) must take a context at the beginning and use this context, passing it from method to method as parameters.

When this method does not solve all your problems, use an event driven mechanism. When your code needs to share something with other components, it sends an event (message) to some bus (topic, queue, whatever). Components can register listeners to listen for events and respond appropriately. In this case, there are no race conditions (except for inserting events into the queue). If you use a ready-to-use queue, rather than its own encoding, it should be quite efficient.

Also take a look at the Actors model.

+6
source

Well, Atomic classes first use locking (through synchronized and mutable keywords) just like you would if you did it manually.

Secondly, immutability is great for multithreading, you no longer need monitor locks, etc., but this is because you can only read your immutable ones, you can change them.

You cannot get rid of synchronized / volatile if you want to avoid race conditions in a multi-threaded Java program (i.e. if several read streams read AND WRITE the same data). Best of all, if you want to improve performance, avoid at least some of the thread-safe built-in classes that make the lock more general and make your own implementation more specific to your context and thus can use more granular synchronization and locking.

Check out this BlockingCache implementation done by the Ehcache guys;

http://www.massapi.com/source/ehcache-2.4.3/src/net/sf/ehcache/constructs/blocking/BlockingCache.java.html

+2
source

One alternative is to make public objects immutable . Read this post for more details.

+2
source

You can perform up to 50 million locks / unlocks per second. If you want this to be more efficient, I suggest using more grain blocking. those. Do not block every little thing, but have locks for large objects. If you have much more locks than threads, you are less likely to have competition, and having more locks can just add overhead.

+1
source

Source: https://habr.com/ru/post/1384093/


All Articles