Synchronization (computer science): Difference between revisions

Content deleted Content added
m Minimization: Fixed grammar
Tags: Mobile edit Mobile app edit Android app edit App section source
 
(28 intermediate revisions by 19 users not shown)
Line 1:
{{short description|Concept in computer science, referring to processes, or data}}
{{distinguish|Data synchronization}}
{{Use American English|date=October 2020}}
{{More citations needed|date=November 2014}}
{{distinguish|Data synchronization}}
 
In [[computer science]], '''synchronization''' is the task of coordinating multiple of [[Process (computer science)|processes]] to join up or [[Handshake (computing)|handshake]] at a certain point, in order to reach an agreement or commit to a certain sequence of action.
 
==Motivation==
Line 13:
''[[Producer–consumer problem|Producer-Consumer:]]'' In a producer-consumer relationship, the consumer process is dependent on the producer process until the necessary data has been produced.
 
''Exclusive use resources:'' When multiple processes are dependent on a resource and they need to access it at the same time, the operating system needs to ensure that only one processor accesses it at a given point in time. This reduces concurrency.
 
=={{Anchor|TSync}}Requirements==
[[File:Multiple Processes Accessing the shared resource.png|thumb|'''Figure 1''': Three processes accessing a shared resource ([[critical section]]) simultaneously.]]
 
Thread synchronization is defined as a mechanism which ensures that two or more concurrent [[process (computer science)|processes]] or [[thread (computer science)|threads]] do not simultaneously execute some particular program segment known as [[critical section]]. Processes' access to critical section is controlled by using synchronization techniques. When one thread starts executing the [[critical section]] (serialized segment of the program) the other thread should wait until the first thread finishes. If proper synchronization techniques<ref>{{cite conference|title=More than you ever wanted to know about synchronization: Synchrobench, measuring the impact of the synchronization on concurrent algorithms|author=Gramoli, V.|conference=Proceedings of the 20th ACM SIGPLAN Symposium on Principles and Practice of Parallel Programming|pages=1–10|year=2015|publisher=ACM|url=http://sydney.edu.au/engineering/it/~gramoli/doc/pubs/gramoli-synchrobench.pdf}}</ref> are not applied, it may cause a [[race condition#Software|race condition]] where the values of variables may be unpredictable and vary depending on the timings of [[context switch]]es of the processes or threads.
{{cite conference
| title=More than you ever wanted to know about synchronization: Synchrobench, measuring the impact of the synchronization on concurrent algorithms
| author=Gramoli, V.
| conference=Proceedings of the 20th ACM SIGPLAN Symposium on Principles and Practice of Parallel Programming
| pages=1–10
| year=2015
| publisher=ACM
| url=http://sydney.edu.au/engineering/it/~gramoli/doc/pubs/gramoli-synchrobench.pdf
}}</ref> are not applied, it may cause a [[race condition#Software|race condition]] where the values of variables may be unpredictable and vary depending on the timings of [[context switch]]es of the processes or threads.
 
For example, suppose that there are three processes, namely 1, 2, and 3. All three of them are concurrently executing, and they need to share a common resource (critical section) as shown in Figure 1. Synchronization should be used here to avoid any conflicts for accessing this shared resource. Hence, when Process 1 and 2 both try to access that resource, it should be assigned to only one process at a time. If it is assigned to Process 1, the other process (Process 2) needs to wait until Process 1 frees that resource (as shown in Figure 2).
 
[[File:Shared Resource access in synchronization environment.png|thumb|'''Figure 2''': A process accessing a shared resource if available, based on some synchronization technique.]]
 
Another synchronization requirement which needs to be considered is the order in which particular processes or threads should be executed. For example, one cannot board a plane before buying a ticket. Similarly, one cannot check e-mails before validating the appropriate credentials (for example, user name and password). In the same way, an ATM will not provide any service until it receives a correct PIN.
 
Other than mutual exclusion, synchronization also deals with the following:
* [[Deadlock (computer science)|deadlock]], which occurs when many processes are waiting for a shared resource (critical section) which is being held by some other process. In this case, the processes just keep waiting and execute no further;
* [[Resource starvation|starvation]], which occurs when a process is waiting to enter the critical section, but other processes monopolize the critical section, and the first process is forced to wait indefinitely;
* [[priority inversion]], which occurs when a high-priority process is in the critical section, and it is interrupted by a medium-priority process. This violation of priority rules can happen under certain circumstances and may lead to serious consequences in real-time systems;
Line 43 ⟶ 34:
==Minimization==
One of the challenges for exascale algorithm design is to minimize or reduce synchronization.
Synchronization takes more time than computation, especially in distributed computing. Reducing synchronization drew attention from computer scientists for decades. Whereas it becomes an increasingly significant problem recently as the gap between the improvement of computing and latency increases. Experiments have shown that (global) communications due to synchronization on distributed computers takes a dominated share in a sparse iterative solver.<ref>{{cite journal|title=Minimizing synchronizations in sparse iterative solvers for distributed supercomputers |author=Shengxin, Zhu and Tongxiang Gu and Xingping Liu|journal=Computers & Mathematics with Applications|volume=67|issue=1|pages=199–209|year=2014|doi=10.1016/j.camwa.2013.11.008|doi-access=free|hdl=10754/668399|hdl-access=free}}</ref> This problem is receiving increasing attention after the emergence of a new benchmark metric, the High Performance Conjugate Gradient (HPCG),<ref>{{cite web|url=http://hpcg-benchmark.org/|title=HPCG Benchmark}}</ref> for ranking the top 500 supercomputers.
{{cite journal
| title=Minimizing synchronizations in sparse iterative solvers for distributed supercomputers
| author=Shengxin, Zhu and Tongxiang Gu and Xingping Liu
| journal=Computers & Mathematics with Applications
| volume=67
| issue=1
| pages=199–209
| year=2014
| doi=10.1016/j.camwa.2013.11.008
| doi-access=free
}}</ref> This problem is receiving increasing attention after the emergence of a new benchmark metric, the High Performance Conjugate Gradient(HPCG),<ref>
{{cite web
| url=http://hpcg-benchmark.org/
| title=HPCG Benchmark
}}
</ref> for ranking the top 500 supercomputers.
 
==Problems==
==Classic problems==
The following are some classic problems of synchronization:
* [[Producer–consumer problem|The Producer–Consumer Problem]] (also called The Bounded Buffer Problem);
Line 68 ⟶ 43:
 
These problems are used to test nearly every newly proposed synchronization scheme or primitive.
 
=== Overhead ===
Synchronization overheads can significantly impact performance in [[parallel computing]] environments, where merging data from multiple processes can incur costs substantially higher—often by two or more orders of magnitude—than processing the same data on a single thread, primarily due to the additional overhead of [[inter-process communication]] and synchronization mechanisms. <ref>{{Cite book |title=Operating System Concepts |isbn=978-0470128725 |last1=Silberschatz |first1=Abraham |last2=Galvin |first2=Peter B. |last3=Gagne |first3=Greg |date=29 July 2008 |publisher=Wiley }}</ref><ref>{{Cite book |title=Computer Organization and Design MIPS Edition: The Hardware/Software Interface (The Morgan Kaufmann Series in Computer Architecture and Design) |date=2013 |publisher=Morgan Kaufmann |isbn=978-0124077263}}</ref><ref>{{Cite book |title=Parallel Programming: Techniques and Applications Using Networked Workstations and Parallel Computers |date=2005 |publisher=Pearson |isbn=978-0131405639}}</ref>
 
==Hardware synchronization==
Line 73 ⟶ 51:
 
A single processor or [[uniprocessor system]] could disable [[interrupt]]s by executing currently running code without [[Preemption (computing)|preemption]], which is very inefficient on [[Multiprocessing|multiprocessor]] systems.<ref name="Wiley2014">{{cite book|last1=Silberschatz|first1=Abraham|last2=Gagne|first2=Greg|last3=Galvin|first3=Peter Baer|title=Operating System Concepts|date=July 11, 2008|publisher=John Wiley & Sons.|isbn=978-0-470-12872-5|edition=Eighth|chapter=Chapter 6: Process Synchronization}}</ref>
"The key ability we require to implement synchronization in a multiprocessor is a set of [[Hardware primitive|hardware primitives]] with the ability to atomically read and modify a memory ___location. Without such a capability, the cost of building basic synchronization primitives will be too high and will increase as the processor count increases. There are a number of alternative formulations of the basic hardware primitives, all of which provide the ability to atomically read and modify a ___location, together with some way to tell if the read and write were performed atomically. These hardware primitives are the basic building blocks that are used to build a wide variety of user-level synchronization operations, including things such as [[Lock (computer science)|locks]] and [[Barrier (computer science)|barriers]]. In general, architects do not expect users to employ the basic hardware primitives, but instead expect that the primitives will be used by system programmers to build a synchronization library, a process that is often complex and tricky."<ref name="Morgan2011">{{cite book|last1=Hennessy|first1=John L.|last2=Patterson|first2=David A.|title=Computer Architecture: A Quantitative Approach|date=September 30, 2011|publisher=Morgan Kaufmann|isbn=978-0-123-83872-8|edition=Fifth|chapter=Chapter 5: Thread-Level Parallelism}}</ref> Many modern pieces of hardware provide such atomic instructions, two common examples being: [[test-and-set]], which operates on a single memory word, and [[compare-and-swap]], which swaps the contents of two memory words.
 
==Support in programming languages==
In [[Java (programming language)|Java]], one way to prevent thread interference and memory consistency errors, is by wrappingprefixing a method signature with the ''synchronized'' keyword, in which case the lock of the declaring object is used to enforce synchronization. A second way is to wrap a block of code in a ''synchronized(someObject){...}'' section, which offers finer-grain control. This forces any thread to acquire the lock of the object represented by ''someObject'' before it can execute the contained block. The lock is automatically released when the thread which acquired the lock, and is then executing the block, leaves thethis block or enters thea waiting state within the block. Any variable updates, made by a thread in a synchronized block, become visible to other threads when they similarly acquire the lock and execute the block. Additionally,For wheneither aimplementation, methodany signatureobject ismay prefixedbe withused theto ''synchronized''provide keyword, thea lock ofbecause theall declaringJava objectobjects ishave used.an For''intrinsic eitherlock'' ofor these''monitor implementations,lock'' anyassociated objectwith maythem bewhen used to provide the lockinstantiated.<ref>{{cite web|title=Intrinsic Locks and Synchronization|url=https://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html|website=The Java Tutorials|publisher=Oracle|access-date=10 November 2023}}</ref>
 
Java ''synchronized'' blocks, in addition to enabling mutual exclusion and memory consistency, enable signaling—i.e., sending events from threads which have acquired the lock and are executing the code block to those which are waiting for the lock within the block. Java ''synchronized'' sections, therefore, combine the functionality of both [[Lock (computer science)|mutexes]] and [[Event (synchronization primitive)|events]] to ensure synchronization. Such a construct is known as a [[Monitor (synchronization)|synchronization monitor]].
 
The [[.NET Framework]] also uses synchronization primitives.<ref>{{cite web|title=Overview of synchronization primitives|url=https://learn.microsoft.com/en-us/dotnet/standard/threading/overview-of-synchronization-primitives|website=Microsoft Learn|date=September 2022 |publisher=Microsoft|access-date=10 November 2023}}</ref> "Synchronization is designed to be cooperative, demanding that every thread follow the synchronization mechanism before accessing protected resources for consistent results. Locking, signaling, lightweight synchronization types, spinwait and interlocked operations are mechanisms related to synchronization in .NET." <ref>{{cite web|title=Synchronization|last=Rouse|first=Margaret|url=https://www.techopedia.com/definition/13390/synchronization-dot-net|website=Techopedia|publisherdate=Techopedia19 August 2011 |access-date=10 November 2023}}</ref>
 
Many programming languages support synchronization and entire specialized [[Synchronous programming language|languages]] have been written for [[Embedded software|embedded application]] development where strictly deterministic synchronization is paramount.
 
==Implementation==
 
===SpinlockSpinlocks===
{{Main article|Spinlock}}
Another effective way of implementing synchronization is by using spinlocks. Before accessing any shared resource or piece of code, every processor checks a flag. If the flag is reset, then the processor sets the flag and continues executing the thread. But, if the flag is set (locked), the threads would keep spinning in a loop and keep checking if the flag is set or not. But, spinlocksSpinlocks are effective only if the flag is reset for lower cycles; otherwise, it can lead to performance issues as it wastes many processor cycles waiting.<ref>{{Cite book|title=Embedded Software Development with ECos|last=Massa|first=Anthony|publisher=Pearson Education Inc|year=2003|isbn=0-13-035473-2}}</ref>
 
===Barriers===
Line 92 ⟶ 72:
Barriers are simple to implement and provide good responsiveness. They are based on the concept of implementing wait cycles to provide synchronization. Consider three threads running simultaneously, starting from barrier 1. After time t, thread1 reaches barrier 2 but it still has to wait for thread 2 and 3 to reach barrier2 as it does not have the correct data. Once all the threads reach barrier 2 they all start again. After time t, thread 1 reaches barrier3 but it will have to wait for threads 2 and 3 and the correct data again.
 
Thus, in barrier synchronization of multiple threads there will always be a few threads that will end up waiting for other threads as in the above example thread 1 keeps waiting for thread 2 and 3. This results in severe degradation of the process performance.<ref name=":0">{{Citecite journal|last=Meng,book Chen, Pan, Yao, Wu|first doi=Jinglei, Tianzhou, Ping, Jun10.1109/HPCC.2014.148 Minghui|date=2014|title chapter=A speculativeSpeculative mechanismMechanism for barrierBarrier Synchronization sychronization|journal title=2014 IEEE InternationalIntl ConferenceConf on High Performance Computing and Communications (HPCC), 2014 IEEE 6th InternationalIntl SymposiumSymp on Cyberspace Safety and Security (CSS) and, 2014 IEEE 11th InternationalIntl ConferenceConf on Embedded Software and SystemsSyst (HPCC,CSS,ICESS) | date=2014 | last1=Meng | first1=Jinglei | last2=Chen | first2=Tianzhou | last3=Pan | first3=Ping | last4=Yao | first4=Jun | last5=Wu | first5=Minghui | pages=858–865 | isbn=978-1-4799-6123-8 }}</ref>
 
The barrier synchronization wait function for i<sup>th</sup> thread can be represented as:
 
(Wbarrier)i = f ((Tbarrier)i, (Rthread)i)
 
Where Wbarrier is the wait time for a thread, Tbarrier is the number of threads has arrived, and Rthread is the arrival rate of threads.<ref>{{Cite book |doi=10.1109/ICIEV.2012.6317471 |isbn=978-1-4673-1154-0|chapter=Process synchronization in multiprocessor and multi-core processor|title=2012 International Conference on Informatics, Electronics & Vision (ICIEV)|pages=554–559|year=2012|last1=Rahman|first1=Mohammed Mahmudur|s2cid=8134329 }}</ref>
 
Experiments show that 34% of the total execution time is spent in waiting for other slower threads.<ref name=":0" />
Line 107 ⟶ 87:
 
Some semaphores would allow only one thread or process in the code section. Such Semaphores are called binary semaphore and are very similar to Mutex. Here, if the value of semaphore is 1, the thread is allowed to access and if the value is 0, the access is denied.<ref>{{Cite book|title=Real-Time Concepts for Embedded Systems|last=Li, Yao|first=Qing, Carolyn|publisher=CMP Books|year=2003|isbn=978-1578201242}}</ref>
 
== Distributed transaction ==
In [[Event-driven architecture|event driven architectures]], synchronous transactions can be achieved through using [[Request–response|request-response]] paradigm and it can be implemented in two ways: <ref name=":02">{{Cite book |last=Richards |first=Mark |title=Fundamentals of Software Architecture: An Engineering Approach |date=2020 |publisher=O'Reilly Media |isbn=978-1492043454}}</ref>
 
* Creating two separate [[Message queue|queues]]: one for requests and the other for replies. The event producer must wait until it receives the response.
* Creating one dedicated ephemeral [[Message queue|queue]] for each request.
 
==Mathematical foundations==
Line 117 ⟶ 103:
An abstract mathematical foundation for synchronization primitives is given by the [[history monoid]]. There are also many higher-level theoretical devices, such as [[process calculi]] and [[Petri net]]s, which can be built on top of the history monoid.
 
== Examples ==
Following are some synchronization examples with respect to different platforms.<ref name="Wiley2012">{{cite book|last1=Silberschatz|first1=Abraham|last2=Gagne|first2=Greg|last3=Galvin|first3=Peter Baer|title=Operating System Concepts|date=December 7, 2012|publisher=John Wiley & Sons.|isbn=978-1-118-06333-0|edition=Ninth|chapter=Chapter 5: Process Synchronization}}</ref>
 
Line 139 ⟶ 125:
===In Solaris===
[[Solaris (operating system)|Solaris]] provides:
* [[Semaphore (programming)|semaphores]];
* [[condition variable]]s;
* adaptive [[adaptiveLock mutex(computer science)|mutexes]]es, binary semaphores that are implemented differently depending upon the conditions;<ref>{{cite web|url=https://docs.oracle.com/cd/E19253-01/817-6223/chp-lockstat-2/index.html|title=Adaptive Lock Probes|website=Oracle Docs}}</ref>
* readers–writerreaders-writer locks:
* [[turnstiles]], queue of threads which are waiting on acquired lock.<ref>{{cite web|url=http://sunsite.uakom.sk/sunworldonline/swol-08-1999/swol-08-insidesolaris.html|title=Turnstiles and priority inheritance - SunWorld - August 1999|first=Jim|last=Mauro|website=sunsite.uakom.sk}}</ref>
 
===In Pthreads===
Line 155 ⟶ 141:
==See also==
* [[Futures and promises]], synchronization mechanisms in pure functional paradigms
* [[Memory barrier]]
 
==References==
{{reflist}}
* {{cite book | last=Schneider | first=Fred B. | title=On concurrent programming | publisher=Springer-Verlag New York, Inc.| date=1997 | isbn=978-0-387-94942-0}}
 
==External links==
Line 171 ⟶ 158:
[[Category:Computer-mediated communication]]
[[Category:Synchronization|Computer science]]
[[Category:Edsger W. Dijkstra]]