3

I'm starting with Threads, Semaphores, volatile variables, etc. I wonder if when I'm using Semaphores it is necessary to define the variable as volatile, I mean:

Having 2 Threads, one increases and the other decreases the variable for example and obviously, before each access I have a mutex that controls at any time only one thread is "playing" with the variable.

It would be necessary to define as volatile?

WikiOverflow
  • 75
  • 3
  • 13
  • 2
    Why not using `AtomicLong` for such operations? Correct and efficient implementation of concurrent operations on the same integer is not that easy. There are readily available classes in JDK which do this work for you. – Tagir Valeev May 09 '15 at 15:20
  • Why are you using a semaphore here? – Sandeep Kaul May 09 '15 at 15:20

3 Answers3

5

From API doc of Semaphore:

Memory consistency effects: Actions in a thread prior to calling a "release" method such as release() happen-before actions following a successful "acquire" method such as acquire() in another thread.

So it is safe to read/write variables that are guarded by a semaphore. No need to declare them as volatile.

isnot2bad
  • 24,105
  • 2
  • 29
  • 50
2

Semaphores should not be used in the place of synchronized because semaphores does not hold exclusive mutual lock even if it is initialized to one, like synchronized on some object. It is true that the semaphore initialized to one, allows only one thread at a time to access the object, which holds the permit. But the thread which holds the permit does not own it, any other thread could release that permit and acquire the permit. So, two threads could get access to the same object at the same time, and if both threads manipulates that object, there will be multi-threading issues like lost update, stale read etc.

In your example of having 2 threads, one increasing and one decreasing the same variable. mutual exclusion is sufficient and volatile declaration is not needed. here I assume mutual exclusion is achieved via synchronized and not by semaphores.

volatile is less strict than synchronized, you may want to use volatile when the operations performed are atomic (read or write). volatile should not be used when the performing read-update-write operation.

Thilak
  • 656
  • 7
  • 15
  • Why do you assume that mutual exclusion is achiveded via synchronized when he don't use synchronized, only semaphores? – Shondeslitch May 10 '15 at 09:33
  • because in the example, he said mutex and never mentioned synchronized and the question was about semaphores and volatile. as it was not not explicitly mentioned, i hope he means synchronized because semaphores are not suitable in such situations – Thilak May 11 '15 at 04:00
1

I wonder if when I'm using Semaphores it is necessary to define the variable as volatile,

I dont think there is any such restriction. A mutex is a mutual exclusion semaphore, a special variant of a semaphore that only allows one locker at a time. It's equivalent to a normal counting semaphore with a count of one and the requirement that it can only be released by the same thread that locked it.

If we talk specifically for Semaphore in Java: A semaphore is a counter of permits and acquire is like decrement which waits rather than go below zero. It has no upper limit. As mentioned in CIP:

The implementation has no actual permit objects, and Semaphore does not associate dispensed permits with threads, so a permit acquired in one thread can be released from another thread. You can think of acquire as consuming a permit and release as creating one; a Semaphore is not limited to the number of permits it was created with.

For your scenario you can share a counter and make it volatile or better use AtomicInteger as they use CAS mechanism which performs really well under low contention.

akhil_mittal
  • 23,309
  • 7
  • 96
  • 95