Lock (computer science)

From Wikipedia, the free encyclopedia
Jump to: navigation, search

In computer science, a lock is a synchronization mechanism for enforcing limits on access to a resource in an environment where there are many threads of execution. A lock is designed to enforce a mutual exclusion concurrency control policy.



A (binary) semaphore is the simplest type of lock. In terms of access to the data, no distinction is made between shared (read only) or exclusive (read and write) modes. Other schemes provide for a shared mode, where several threads can acquire a shared lock for read-only access to the data. Other modes such as exclusive, intend-to-exclude and intend-to-upgrade are also widely implemented.

Independent of the type of lock chosen above, locks can be classified by what happens when the lock strategy prevents progress of a thread. Most locking designs block the execution of the thread requesting the lock until it is allowed to access the locked resource. A spinlock is a lock where the thread simply waits ("spins") until the lock becomes available. It is very efficient if threads are only likely to be blocked for a short period of time, as it avoids the overhead of operating system process re-scheduling. It is wasteful if the lock is held for a long period of time, or if the progress of the thread that is holding the lock depends on preemption of the locked thread.


Uniprocessor architectures have the option of using uninterruptable sequences of instructions ‒ using special instructions or instruction prefixes to disable interrupts temporarily ‒ but this technique does not work for multiprocessor shared-memory machines. Proper support for locks in a multiprocessor environment can require quite complex hardware or software support, with substantial synchronization issues.


if (lock == 0) {
    /* lock free - set it */
    lock = myPID; 




class Account {     // this is a monitor of an account
  long val = 0;
  object thisLock = new object();
  public void Deposit(const long x) {
    lock (thisLock) {   // only 1 thread at a time may execute this statement
      val += x;
  public void Withdraw(const long x) {
    lock (thisLock) {
      val -= x;

The code lock (this) is a problem if the instance can be accessed publicly.[1]


  public void SomeMethod () {
	// do stuff


Before being introduced to lock granularity, one needs to understand three concepts about locks.

  • deadlock: The situation when each of two tasks is waiting for a lock that the other task holds. Unless something is done, the two tasks will wait forever.




Database locks[edit]

Main article: Lock (database)


There are mechanisms employed to manage the actions of multiple concurrent users on a database - the purpose is to prevent lost updates and dirty reads. The two types of locking are Pessimistic and Optimistic Locking.

  • Pessimistic locking: A user who reads a record, with the intention of updating it, places an exclusive lock on the record to prevent other users from manipulating it. This means no one else can manipulate that record until the user releases the lock. The downside is that users can be locked out for a very long time, thereby slowing the overall system response and causing frustration.



  • They cause blocking, which means some threads/processes have to wait until a lock (or a whole set of locks) is released. If one of the threads holding a lock dies, stalls/blocks or goes into any sort of infinite loop, other threads waiting for the lock may wait forever.
  • Locks can be vulnerable to failures and faults that are often very subtle and may be difficult to reproduce reliably. One example is the deadlock, where (at least) two threads each hold a lock that the other thread holds and will not give up until it has acquired the other lock.
  • Lock contention limits scalability and adds complexity.
  • Balances between lock overhead and contention can be unique to given problem domains (applications) as well as sensitive to design, implementation, and even low-level system architectural changes. These balances may change over the life cycle of any given application/implementation and may entail tremendous changes to update (re-balance).
  • Locks are only composable (e.g., managing multiple concurrent locks in order to atomically delete Item X from Table A and insert X into Table B) with relatively elaborate (overhead) software support and perfect adherence by applications programming to rigorous conventions.
  • Priority inversion. A low-priority thread/process holding a common lock can prevent high-priority threads/processes from proceeding. Priority ceiling protocol can be used to prevent priority inversion. Priority inheritance can be used to minimize priority-inversion duration.
  • Convoying. All other threads have to wait, if a thread holding a lock is descheduled due to a time-slice interrupt or page fault (See lock convoy)
  • Hard to debug: Bugs associated with locks are time dependent. They are extremely hard to replicate.

It's possible to use a concurrency control strategy that doesn't have some or all of these problems. For example, using a funnel or serializing tokens can make software immune to the biggest problem: deadlocks. Alternatively, it's possible to avoid locks entirely using non-blocking synchronization methods, like lock-free programming techniques and transactional memory. However, these alternative methods often require that the actual lock mechanisms be implemented at a more fundamental level of the operating software. Therefore, they may only relieve the application level from the details of implementing locks, with the problems listed above still needing to be dealt with beneath the application.


Language support[edit]

Language support for locking depends on the language used:

  • There is no API to handle mutexes in the ISO/IEC standard for C. The current ISO C++ standard, C++11, supports threading facilities. The OpenMP standard is supported by some compilers, and this provides critical sections to be specified using pragmas. The POSIX pthread API provides lock support.[5] Visual C++ allows adding the synchronize attribute in the code to mark methods that must be synchronized, but this is specific to "COM objects" in the Windows architecture and Visual C++ compiler.[6] C and C++ can easily access any native operating system locking features.
  • Java provides the keyword synchronized to put locks on blocks of code, methods or objects[7] and libraries featuring concurrency-safe data structures.
  • In the C# programming language, the lock keyword can be used to ensure that a thread has exclusive access to a certain resource.
  • VB.NET provides a SyncLock keyword for the same purpose of C#'s lock keyword.
  • Python does not provide a lock keyword, but it is possible to use a lower level mutex mechanism to acquire or release a lock.[8]
  • Ruby also doesn't provide a keyword for synchronization, but it is possible to use an explicit low level mutex object.[9]
  • In x86 Assembly, the LOCK prefix prevents another processor from doing anything in the middle of certain operations: it guarantees atomicity.
  • Objective-C provides the keyword "@synchronized"[10] to put locks on blocks of code and also provides the classes NSLock,[11] NSRecursiveLock,[12] and NSConditionLock[13] along with the NSLocking protocol[14] for locking as well.
  • Ada is probably worth looking at too for a comprehensive overview, with its protected objects[15][16] and rendezvous.

See also[edit]


  2. ^ "ThreadPoolPriority, and MethodImplAttribute". http://msdn.microsoft.com/en-us/magazine/cc163896.aspx: MSDN. p. ??. Retrieved 2011-11-22. 
  3. ^ "C# From a Java Developer's Perspective". http://www.25hoursaday.com/CsharpVsJava.html#attributes. Retrieved 2011-11-22. 
  4. ^ "Designing Data Tier Components and Passing Data Through Tiers". Microsoft. August 2002. Retrieved 2008-05-30. 
  6. ^ "Synchronize". msdn.microsoft.com. Retrieved 2008-05-30. 
  7. ^ "Synchronization". Sun Microsystems. Retrieved 2008-05-30. 
  8. ^ Lundh, Fredrik (July 2007). "Thread Synchronization Mechanisms in Python". Retrieved 2008-05-30. 
  15. ^ ISO/IEC 8652:2007. "Protected Units and Protected Objects". Ada 2005 Reference Manual. Retrieved 2010-02-27. "A protected object provides coordinated access to shared data, through calls on its visible protected operations, which can be protected subprograms or protected entries." 

External links[edit]