How to make Scala object thread-safe.
class Stack {
case class Node(value: Int, var next: Node)
private var head: Node = null
private var sz = 0
def push(newValue: Int) {
head = Node(newValue, head)
sz += 1
}
def pop() = {
val oldNode = head
head = oldNode.next
oldNode.next = null
sz -= 1
}
def size = sz //I am accessing sz from two threads
}
This class is clearly not threadsafe. I want to make it threadsafe.
Thanks in Advance,
HP
Just because it's fun, you can also make this thread-safe by popping head into an AtomicReference and avoiding synchronized altogether. Thusly:
final class Stack {
private val head = new AtomicReference[Node](Nil)
#tailrec
def push(newValue: Int) {
val current = head.get()
if (!head.compareAndSet(current, Node(newValue, current))) {
push(newValue)
}
}
#tailrec
def pop(): Option[Int] = head.get() match {
case current # Cons(v, tail) => {
if (!head.compareAndSet(current, tail))
pop()
else
Some(v)
}
case Nil => None
}
def size = {
def loop(node: Node, size: Int): Int = node match {
case Cons(_, tail) => loop(tail, size + 1)
case Nil => size
}
loop(head.get(), 0)
}
private sealed trait Node
private case class Cons(head: Int, tail: Node) extends Node
private case object Nil extends Node
}
This avoids locking entirely and provides substantially better throughput than the synchronized version. It's worth noting though that this sort of fake thread-safe data structure is rarely a good idea. Handling synchronization and state management concerns at the level of a data structure is a bit like trying to handle IO exceptions within an XML parser: you're trying to solve the right problem in the wrong place and you don't have the information needed to do that. For example, the stack above is perfectly safe, but it's certainly not consistent across operations (e.g. you could push and subsequently pop onto a stack and get None as a result).
Your better option is to use an immutable stack (like List) and throw that into an AtomicReference if you need shared mutable state.
To my mind, the easiest way to make this meaningfully thread-safe would be as follows:
class Stack {
case class Node(value: Int, var next: Node)
private var head: Node = null
private var sz : Int = 0
def push(newValue: Int) {
synchronized {
head = Node(newValue, head)
sz += 1
}
}
def pop() : Option[Int] = {
synchronized {
if ( sz >= 1 ) {
val ret = Some(head.value)
val oldNode = head
head = oldNode.next
oldNode.next = null
sz -= 1
ret
} else {
None
}
}
}
def size = synchronized { sz }
}
This implementation would allow you to ensure that push's and pop's would be atomic, with pop returning a Some wrapping the value it removed from the top of the stack or None if the stack was already empty.
As a note, access to the size is synchronized, but you have no way of guaranteeing that it will be correct at any point after it is returned, since multiple threads are able to access the stack, potentially altering its size. If you really do need to know the size exactly accurately, you would have to go about this differently, synchronizing on the whole stack when you use it.
Related
I wrote the following simple application:
object Main extends App {
var v: Int = 0
val t = new Thread(() => v = 1)
t.start()
t.join()
println(v) //prints 1
}
The thing that I was confused by was that we modify local variable from another thread... And that modification (made by the other thread) is visible in the main thread.
I thought local variables are always reside in a stack (stack memory the bottom is pointed to rsp register). I thought the stack memory is allocated for each thread in the application.
Upd: Even if we modify the app as follows it prints the same:
object Main {
def main(args: Array[String]) = {
var v: Int = 0
val t = new Thread(() => v = 1)
t.start()
t.join()
println(v) //prints 1
}
}
v is not a local variable in this case. It is a member of Main singletone object.
Update for the second example:
Closure () => v = 1 is compiled into an anonymous class that captures all variables it depends on. Stack-allocated primitives are turned into heap-allocated objects.
Here it is explained in details:
How does the memory management of closures in Scala work?
What this is doing is turning what appears to be a stack object into a heap object. In Java you can do this using array of 1 without adding special classes as Scala does.
public static void main(String... args) {
int[] v = { 0 };
Thread t = new Thread(() => v[0] = 1);
t.start();
t.join();
println(v[0]); //prints 1
}
In a previous SO post I asked about an idiomatic way to make a container class wrapping an immutable collection thread-safe. Answers that I received all involved using various flavors of read/write locks or synchronization which is not what I wanted.
Let me ask a different question. How do I make the following class that wraps an immutable container immutable? The methods add/remove need to return a new MyContainer class instance suitably altered, but I can't quite see how to do it...
class MyContainer[A] {
// method that returns a new MyContainer that includes the additional thing...
def add(thing: A): MyContainer[A] = {
???
}
def filter(p: A => Boolean): Option[Iterable[A]] = {
val filteredThings = backingStore.values.filter(p)
if (filteredThings.isEmpty) None else Some(filteredThings)
}
// method that returns a new MyContainer that does not include the thing with given uuid
def remove(uuid: UUID): MyContainer[A] = {
???
}
# volatile private[this] var backingStore = immutable.HashMap.empty[UUID, A]
}
Thoughts?
EDIT: In response to comment, one possible solution would be something similar to the following...
class MyContainer[A](val backingStore: immutable.HashMap[UUID, A]) {
def add(thing: A): MyContainer[A] = {
new MyContainer(backingStore + (thing.uuid -> thing))
}
def filter(p: A => Boolean): Option[Iterable[A]] = {
val filteredThings = backingStore.values.filter(p)
if (filteredThings.isEmpty) None else Some(filteredThings)
}
def remove(uuid: UUID): MyContainer[A] = {
new MyContainer(backingStore - uuid)
}
}
...backingStore is no longer private (but could put private in constructor). More thoughts?
You need a way to construct a new MyContainer that already contains some elements and preferably maintain the same UUIDs. That means you will essentially need a constructor that initalizes backingStore. However, if you don't want to expose it in any way, you can make the constructor private, and provide an overloaded constructor that only allows external code to create an empty collection to begin with (let's say). backingStore can simply be moved into a private constructor for this.
class MyContainer[A] private (backingStore: HashMap[UUID, A]) {
def this() = this(HashMap.empty[UUID, A])
def add(thing: A): MyContainer[A] = {
val uuid: UUID = UUID.randomUUID() // or however the UUID is generated
new MyContainer(backingStore + ((uuid, thing)))
}
def remove(uuid: UUID): MyContainer[A] =
new MyContainer(backingStore - uuid)
}
scala> val container = new MyContainer[String]()
scala> container.add("a").add("b").add("c")
res2: MyContainer[String] = MyContainer#4a183d02
It's really up to you want you want to expose in the API, though. I wasn't sure what you were going for with filter so I removed it from my example.
I have the following problem definition:
Design a lock-free simple linked list with the following operations:
Add(item): add the node to the beginning (head) of the list
Remove(item): remove the given item from the list
Below is shown the code implemented so far:
public class List<T>
{
private readonly T _sentinel;
private readonly Node<T> _head;
public List()
{
_head = new Node<T>();
_sentinel = default(T);
}
public List(T item)
{
_head = new Node<T>(item);
_sentinel = item;
}
public void Add(T item)
{
Node<T> node = new Node<T>(item);
do
{
node.Next = _head.Next;
}
while (!Atomic.CAS(ref _head.Next, node.Next, node));
}
public void Remove(Node<T> item)
{
Node<T> next;
Node<T> oldItem = item;
if (item.Value.Equals(_sentinel))
return;
item.Value = _sentinel;
do
{
next = item.Next;
if (next == null)
{
Atomic.CAS(ref item.Next, null, null);
return;
}
} while (!Atomic.CAS(ref item.Next, next, next.Next));
item.Value = next.Value;
}
}
The head is actually a dummy (sentinel) node kept for ease of use. The practical head is actually _head.Next.
The problem is on the remove operation when trying to remove the last element of the list:
On the remove part there are two cases:
The node has a following not-null next pointer: then do the CAS operation and steal the value data of the next item removing actually the next item
The problematic case is when the element to remove is the last one in the list:
Do Atomically: If (item == oldItem and item.Next == null) then item = null where oldItem is a pointer to the item to remove;
So I want to do is in the case of removing C node:
if(C==old-C-reference and C.Next == null) then C = null => all atomically
The problem is that I have a CAS only on a single object.
How can I solve this problem atomically? Or is there a better way of doing this remove operation that I'm missing out here?
when removing B we do a trick by copying C's contents to B and removing C: B.Next = C.Next (in the loop) and B.Value = C.Value after the move succeeded
So you need to atomically modify two memory locations. CAS in .NET does not support that. You can, however, wrap those two values in another object that can be swapped out atomically:
class ValuePlusNext<T> {
T Value;
Node<T> Next;
}
class Node<T> {
ValuePlusNext<T> Value;
}
Now you can write to both values in one atomic operation. CAS(ref Value, new ValuePlusNext<T>(next.Value, next.Value.Next). Something like that.
It is strange that ValuePlusNext has the same structure that your old Node class had. In a sense you are now managing two physical linked list node for each logical one.
while (true) {
var old = item.Value;
var new = new ValuePlusNext(...);
if (CAS(ref Value, old, new)) break;
}
I want to implement something like the producer-consumer problem (with only one information transmitted at a time), but I want the producer to wait for someone to take his message before leaving.
Here is an example that doesn't block the producer but works otherwise.
class Channel[T]
{
private var _msg : Option[T] = None
def put(msg : T) : Unit =
{
this.synchronized
{
waitFor(_msg == None)
_msg = Some(msg)
notifyAll
}
}
def get() : T =
{
this.synchronized
{
waitFor(_msg != None)
val ret = _msg.get
_msg = None
notifyAll
return ret
}
}
private def waitFor(b : => Boolean) =
while(!b) wait
}
How can I changed it so the producers gets blocked (as the consumer is) ?
I tried to add another waitFor at the end of but sometimes my producer doesn't get released.
For instance, if I have put ; get || get ; put, most of the time it works, but sometimes, the first put is not terminated and the left thread never even runs the get method (I print something once the put call is terminated, and in this case, it never gets printed).
This is why you should use a standard class, SynchronousQueue in this case.
If you really want to work through your problematic code, start by giving us a failing test case or a stack trace from when the put is blocking.
You can do this by means of a BlockingQueue descendant whose producer put () method creates a semaphore/event object that is queued up with the passed message and then the producer thread waits on it.
The consumer get() method extracts a message from the queue and signals its semaphore, so allowing its original producer to run on.
This allows a 'synchronous queue' with actual queueing functionality, should that be what you want?
I came up with something that appears to be working.
class Channel[T]
{
class Transfer[A]
{
protected var _msg : Option[A] = None
def msg_=(a : A) = _msg = Some(a)
def msg : A =
{
// Reading the message destroys it
val ret = _msg.get
_msg = None
return ret
}
def isEmpty = _msg == None
def notEmpty = !isEmpty
}
object Transfer {
def apply[A](msg : A) : Transfer[A] =
{
var t = new Transfer[A]()
t.msg = msg
return t
}
}
// Hacky but Transfer has to be invariant
object Idle extends Transfer[T]
protected var offer : Transfer[T] = Idle
protected var request : Transfer[T] = Idle
def put(msg : T) : Unit =
{
this.synchronized
{
// push an offer as soon as possible
waitFor(offer == Idle)
offer = Transfer(msg)
// request the transfer
requestTransfer
// wait for the transfer to go (ie the msg to be absorbed)
waitFor(offer isEmpty)
// delete the completed offer
offer = Idle
notifyAll
}
}
def get() : T =
{
this.synchronized
{
// push a request as soon as possible
waitFor(request == Idle)
request = new Transfer()
// request the transfer
requestTransfer
// wait for the transfer to go (ie the msg to be delivered)
waitFor(request notEmpty)
val ret = request.msg
// delete the completed request
request = Idle
notifyAll
return ret
}
}
protected def requestTransfer()
{
this.synchronized
{
if(offer != Idle && request != Idle)
{
request.msg = offer.msg
notifyAll
}
}
}
protected def waitFor(b : => Boolean) =
while(!b) wait
}
It has the advantage of respecting symmetry between producer and consumer but it is a bit longer than what I had before.
Thanks for your help.
Edit : It is better but still not safeā¦
Is there already a way in groovy to collect objects following a property while not null ?
Object.metaClass {
collectWhileNotNull = { Closure follow ->
def result = []
def previous = null
for (def current = delegate; !current.is(previous) && (current != null); current = follow(current)){
result << current
previous = current
}
return result
}
}
It is useful for recursive data structure.
An example of usage for a groovy.util.Node :
Closure getAncestors = { Node n -> n.collectWhileNotNull{ it.parent() }.tail().reverse() }
You can use a Generator class (this is also the name of the necessary pattern) from cookbook.