Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

locking only 1 operation?

ive been asking myself : "why should i use lock to only one statement"...

(IMHO - if its 1 operation only like an assignment - so there shouldnt be a problem..)?

then i saw this :

As a basic rule, you need to lock around accessing any writable shared field. Even in the simplest case—an assignment operation on a single field—you must consider synchronization. In the following class, neither the Increment nor the Assign method is thread-safe:

class ThreadUnsafe
{
  static int _x;
  static void Increment() { _x++; }  
  static void Assign() { _x = 123; }
}

can you please tell me why this is not thread safe ? ive been running many scripts in my head and couldnt find any problem...

like image 952
Royi Namir Avatar asked May 14 '12 08:05

Royi Namir


People also ask

What is lock operation?

< Operating System Design. Wikipedia has related information at Lock (computer science) Locks are methods of synchronization used to prevent multiple threads from accessing a resource at the same time. Usually, they are advisory locks, meaning that each thread must cooperate in gaining and releasing locks.

What is the difference between a shared lock and exclusive lock?

The two types are exclusive and shared locks. Exclusive locks can be active or retained; shared locks can only be active (see Active and retained states for locks ). Note that there are no delete locks in RLS mode.


2 Answers

Here's an example of why your example is not thread-safe. Initially, _x = 0. Let's say you run Increment and Assign in parallel. If the methods were thread-safe, the result should be either 100 (if increment is executed before assign) or 101 (if increment is executed after assign).

(EDIT: Note that each thread has it's own working stack!)

 Thread 1 (executing Increment)    Thread 2 (executing Assign 100)
 -----------------------------------------------------------------
 read _x onto stack       (= 0)
                                   put 100 on top of stack
                                   write top of stack to _x (= 100)
 increment top of stack   (= 1)
 write top of stack to _x (= 1)

_x is now 1, which is neither 100 nor 101.

Of course, it could be that your incrementation method is compiled into single, atomic operation by the compiler. But you cannot rely on this, unless it is specifically guaranteed by the compiler that you use.


If you use a lock, the following happens:

 Thread 1 (executing Increment)    Thread 2 (executing Assign 100)
 -----------------------------------------------------------------
 lock (success)
 read _x onto stack       (= 0)
                                   lock (lock already taken; 
                                   |     wait until Thead 1's lock is released)
 increment top of stack   (= 1)    |
 write top of stack to _x (= 1)    |
 unlock                            |
                                   +> (success)
                                   put 100 on top of stack
                                   write top of stack to _x (= 100)
                                   unlock

The result is now 100. Basically, the lock ensures that two locked blocks do not overlap.

like image 70
Heinzi Avatar answered Oct 08 '22 23:10

Heinzi


The increment operation produces this MSIL...

.method private hidebysig static void  Increment() cil managed
{
  // Code size       14 (0xe)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ldsfld     int32 ThreadUnsafe::_x
  IL_0006:  ldc.i4.1
  IL_0007:  add
  IL_0008:  stsfld     int32 ThreadUnsafe::_x
  IL_000d:  ret
} // end of method ThreadUnsafe::Increment

So you can see that, even at the MSIL level, the increment is not atomic. The JIT compiler might conceivably do something clever to turn this back into an atomic increment at the machine level, but we certainly can't depend on that. Imagine 2 threads incrementing the same X with their "load" and "store" operations overlapped - you can see that it's possible to end up with X = X + 1 instead of X + 2.

Wrapping your increment inside a lock means they can't overlap.

like image 27
Martin Avatar answered Oct 08 '22 23:10

Martin