Java Keywords (Part XXI): synchronized
Java keyword list
abstract | continue | for | new | switch |
assert | default | goto* | package | synchronized |
boolean | do | if | private | this |
break | double | implements | protected | throw |
byte | else | import | public | throws |
case | enum | instanceof | return | transient |
catch | extends | int | short | try |
char | final | interface | static | void |
class | finally | long | strictfp | volatile |
const* | float | native | super | while |
Keyword marked with an asterisk (*) are keywords that, although valid, are not used by programmers.
Before diving into the use of the synchronized
keyword, we must understand concurrency. I will do my best to summarize the concept of concurrency first and then provide use cases for using synchronization.
What is concurrency?
The dictionary definition of the word concurrent is "occurring, arising, or operating at the same time." In computing, this means that a certain operation, or group of operations, must be executed at the same time. In modern computing, this is often taken for granted. I am old enough to remember the old days where you could only execute one program at a time. So, if you wanted to execute a second program, you had to terminate the first before attempting to run the second. Even programs like Microsoft Word had to abide by these rules: If you wanted to open a second document, you had to close the first. Eventually, CPUs went from single core, to dual, to quad, etc., giving us the ability to execute programs "simultaneously." Notice how the word simultaneously was purposely enclosed in quotes. Please do not mistake "concurrency" with "parallelism." Concurrency is the task of running and managing (mainly managing) the multiple computations at the same time. While parallelism is the task of running multiple computations simultaneously. With concurrent processing, the Operating System takes on the task of executing programs simultaneously, but at any given instance of time it's actively working on one specific task. Take for example the following use case. A person opens Microsoft Word and starts editing 3 documents for a task at work. At any given moment, the person is actively editing one document while the other two are minimized. The person switches between document until all three documents are properly edited. The person edited those documents concurrently, not in parallel. I hope that clarifies the difference between concurrent and parallel processing. Regardless, synchronization is extremely important for both concurrent and parallel processing.What is synchronization?
Synchronization means the act of being synchronous. That's not very helpful if you don't understand synchronicity. Synchronous means "happening, existing, or arising at precisely the same time." You often see hear in movies "let's synchronize our watches." When they do this, they set the time on their watches to the exact same value, down to the millisecond. Synchronization involves precision. One millisecond off, and you are no longer synchronized. This is the same in computing. Suppose you write code that reads from and writes to a file. Your application is multi-threaded because different users may decide to read or write to files at different points in time. While you may need to support many simultaneous users, what happens if all your concurrent users need to access the same file at the same time? This is not necessarily a problem if they all need to read the file, but what happens if one decides to write to the file? What happens first? What if two or more decide to write to the file? Will one user overwrite inadvertently what another user wrote? If these actions are not correctly handled, this can be a huge mess. To avoid this mess, as programmers, we need to establish some kind of control for code that can be executed concurrently. The keywordsynchronized
helps with, but does not fix, concurrency issues.
This article will not get into why or when synchronize is needed. That is a very long and complicated topic. It will simply show you how to use this keyword. To learn more about concurrent programming in Java, please visit The Java™ Tutorials Lesson: Concurrency.
Using the synchronized
keyword
The best strategy for using the synchronized
keyword is to limit the scope of the synchronized block to the smallest size possible. This means you can synchronize a single line of code inside a function. This is known as a synchronized statement.
public void someMethod() {
// step 1
// step 2
// step 3
// synchronized statement
synchronized (...) {
// step 4
}
// step 5
}
public synchronized void someMethod() {
// code omitted
}
What goes inside the parentheses of the synchronized
block?
Remember the example of the synchronized statement?
synchronized (...) {
// step 4
}
Intrinsic Locks
Unlike synchronized methods, synchronized statements must specify the object that provides the intrinsic lock. Synchronization is built around an internal entity known as the intrinsic lock. Every object has one. What that means for this topic is that you can place any object instance in place of the ellipsis (within reason). Before I continue, I must point out the obvious. Synchronized methods did not have an object serving as the intrinsic lock, or did they? As a matter of fact, they do have an instrinsic lock. In the case of synchronized methods, the object containing the method is the instrinsic lock. In other words, the intrinsic lock is the object itself (this
). The only difference is that you do not set it explicitly. It is implicit. In the case of synchronized statements, you could pass this
, or you can pass an instance of another object serving as the lock. A word of caution, Java recommends not to use String
or any of the other primitive type wrapper classes, like Integer
, Long
, and others. You can also place (this
) as the lock.
synchronized (this) {
// step 4
}
synchronized
is used for both. In the case of synchronized methods, the keyword synchronized
is placed immediately after the access modifier. In the case of synchronized statements, you must provide an intrinsic lock object; either this
or some other instance of an object that will be served as the lock.
To learn more about concurrency in Java, click on the link I previously provided. To learn mora about using synchronized
keyword, visit Synchronized Methods and Intrinsic Locks and Synchronization to learn more about synchronized statements.
That is all for this article. I hope it was useful to you. See you next time! Next up, Part XXII: volatile
Comments
Post a Comment