wordssynchronized
One, foreword
Synchronized is a surefire way to get started with Java locks, and being able to pronounce it can be a plus in future interviews (I’ve interviewed people who said “syn” instead of “syn”), but it’s a bit unprofessional. However the problem is not big, can use, understand the principle is the most important.
The content will go from simple to difficult, and sometimes you can give up some of the difficult things. I’ll mark it and it’ll be easier to see later
Second, the DEMO
Hello world!!
Example: Xiaoqiang and Xiaoming live together, but there is only one toilet, they have to do every day is to grab the pit, so how to use the code implementation to write?
/ * * *@authorDay and night of Muzi * < P > * Human entity class */
public class Person {
/ / name
private String name;
/ / go to the bathroom
public void gotoWc(a) {
Wc.useWc(this);
}
public String getName(a) {
return name;
}
public void setName(String name) {
this.name = name; }}/ * * *@authorMuzi day and night * * Toilet entity class */
public class Wc {
/** * How to use the toilet *@paramP People who use toilets */
public static void useWc(Person p){
try{
System.out.println(p.getName()+"Using the toilet!!");
TimeUnit.SECONDS.sleep(10);
System.out.println(p.getName()+"It's gone!!");
} catch (Exception e) {
// The toilet has to be finished in case it breaks down
System.out.println(p.getName()+"It's gone!!"); }}}/ * * *@authorWood of day and night * this test is small strong and small bright to discuss good say small strong you come to small strong finish thing small bright again * this won't produce conflict because be to discuss good order to carry out * everybody knows order is won't give what problem */
public class SyncTest {
public static void main(String[] args) {
// Cockroaches
Person xiaoqiang = new Person();
xiaoqiang.setName("Small strong");
// Xiaoming object
Person xiaoming = new Person();
xiaoming.setName("Xiao Ming");
/ / go to the bathroomxiaoqiang.gotoWc(); xiaoming.gotoWc(); }}Copy the code
Toilet-going process:
What if the two go their own way without discussion?
/ * * *@authorDay and night of wood */
public class SyncTest02 {
public static void main(String[] args) {
// Cockroaches
Person xiaoqiang = new Person();
xiaoqiang.setName("Small strong");
// Xiaoming object
Person xiaoming = new Person();
xiaoming.setName("Xiao Ming");
// Start two threads and let them do their own work
new Thread(()->xiaoqiang.gotoWc()).start();
newThread(()->xiaoming.gotoWc()).start(); }}Copy the code
Toilet-going process:
The picture above is obviously visible, xiaoqiang did not finish it, Xiaoming went up, if the small still gather together live, how to do big? The picture thinks ~~
At this point you’re probably thinking, is there a lock on the bathroom door? Can’t someone just go in and lock it up?
Bingo!
/ * * *@authorMuzi's day and night * * After the transformation of the toilet entity class */
public class Wc {
/** * Synchronized: Lock the toilet if you use it first!! *@paramP People who use toilets */
public static synchronized void useWc(Person p){
try{
System.out.println(p.getName()+"Using the toilet!!");
TimeUnit.SECONDS.sleep(10);
System.out.println(p.getName()+"It's gone!!");
} catch (Exception e) {
// The toilet has to be finished in case it breaks down
System.out.println(p.getName()+"It's gone!!"); }}}/ * * *@authorDay and night of wood */
public class SyncTest02 {
public static void main(String[] args) {
// Cockroaches
Person xiaoqiang = new Person();
xiaoqiang.setName("Small strong");
// Xiaoming object
Person xiaoming = new Person();
xiaoming.setName("Xiao Ming");
// Open two threads, neither of whom can do their own work.
Lock whoever comes in first
new Thread(()->xiaoqiang.gotoWc()).start();
newThread(()->xiaoming.gotoWc()).start(); }}Copy the code
Toilet-going process:
It can be seen that Xiaoqiang finished first and Xiaoming went up again, so that there would be no problem.
Some people may ask, only locked, did not unlock, xiao Ming how to get in?
This is a feature of synchronized, which releases the lock automatically after the code in the synchronized package is executed.
So avoid forgetting to release the lock, bring embarrassment ~
Pretend academic discussions
3.1 Why is it locked?
Take the toilet, for example, for yourself. Come up with the word “shared resources.
3.2 Object Lock Class lock
1) An object lock, as its name implies, locks an object
/ * * *@authorMuzi night and day * object lock */
public class SyncObject {
/** * Cumulative value (shared resource) */
int count = 0;
/** * lock object */
private Object lock = new Object();
public static void main(String[] args) {
SyncObject so = new SyncObject();
/ / thread 1
new Thread(()->{
try {
for(;;) { TimeUnit.SECONDS.sleep(2); so.increaseCount(); }}catch (Exception e) {
System.err.println("Error"); }},Thread 1 "").start();
/ / thread 2
new Thread(()->{
try {
for(;;) { TimeUnit.SECONDS.sleep(2); so.increaseCount(); }}catch (Exception e) {
System.err.println("Error"); }},Thread 2 "").start();
}
/** * count adds */
public void increaseCount(a){
/ / lock
synchronized (lock){
count = count+1;
System.out.println(Thread.currentThread().getName()+" count="+count); }}}Copy the code
In this example, two threads increment count and lock the object. This is called an object lock.
Synchronized (this) what is this? This is the current object, which is also the object lock,
Synchronized (this) is the equivalent of adding synchronized to a method, both of which are the current objects of the lock
/** * count adds */
public void increaseCount(a){
/ / lock
synchronized (this){
count = count+1;
System.out.println(Thread.currentThread().getName()+" count="+count); }}/** * count */
public synchronized void increaseCount02(a){
count = count+1;
System.out.println(Thread.currentThread().getName()+" count="+count);
}
Copy the code
2) Class locking, as the name implies, is to lock a class
After each Class is loaded into memory, it generates an object lock of type Class
It’s actually locking an object but it’s a special object, it’s a class
/ * * *@authorMuzi night and day * object lock */
public class SyncObject03 {
/** * Cumulative value (shared resource) */
static int count = 0;
/** * lock object */
private Object lock = new Object();
public static void main(String[] args) {
SyncObject03 so = new SyncObject03();
/ / thread 1
new Thread(()->{
for (;;){
SyncObject03.increaseCount();
}
},Thread 1 "").start();
/ / thread 2
new Thread(()->{
for (;;){
SyncObject03.increaseCount();
}
},Thread 2 "").start();
}
/** * count adds */
public synchronized static void increaseCount(a){
/ / lock
try {
count = count+1;
System.out.println(Thread.currentThread().getName()+" count="+count);
TimeUnit.SECONDS.sleep(1);
} catch (Exception e){
System.err.println("Wrong!"); }}/** * count adds */
public void increaseCount02(a){
synchronized(SyncObject03.class){
/ / lock
try {
count = count+1;
System.out.println(Thread.currentThread().getName()+" count="+count);
TimeUnit.SECONDS.sleep(1);
} catch (Exception e){
System.err.println("Wrong!"); }}}}Copy the code
Both of these methods are class locks.
3.3 Can the unlocked method of the current object be executed when the locked method is executed?
This is a tip of the toe answer, but many interviewers ask it. Asked after you meng ~~ can’t?
The answer is: yes!
Why is it possible? Because of love so love ~~ wrong, again.. Because can so can ~~
Xiao Ming is eating, give a lock to the bowl, others can not use, that xiao Ming can watch his idol DENG Zi Chess singing at the same time?
If anyone says no, he will not be allowed to play with mobile phones, pads or computers during meals. Let him eat (it’s a pig)
/ * * *@authorDay and night * possible interview questions */
public class SyncObject04 {
private Object lock = new Object();
public static void main(String[] args) throws InterruptedException {
SyncObject04 so = new SyncObject04();
/ / thread 1
new Thread(()->{
so.increaseCount();
},Thread 1 "").start();
Thread.sleep(2000);
/ / thread 2
new Thread(()->{
so.lookMv();
},Thread 2 "").start();
}
/** * eat */
public void increaseCount(a){
/ / lock
synchronized (this) {try{
System.out.println("吃饭 ");
// You can also chat with girls here
chatWithGirl();
TimeUnit.SECONDS.sleep(10);
} catch (Exception e) {
System.err.println("I dropped my food on the floor.");
}
System.out.println("After dinner"); }}/** * watch the concert video */
public void lookMv(a){
System.out.println("Watch the concert video");
}
/** ** ** /
public void chatWithGirl(a){
System.out.println("Talk to a beautiful woman."); }}Copy the code
3.4 reentrant
Can you sum it up in one sentence?
Cough: The same thread can call two methods with the same lock without blocking.
Example: The same person can use the same pair of chopsticks (chopsticks locked) and eat different dishes ~~
Eat fish to get the lock, in the eat fish method call eat salad method, is able to call success because the two methods use the same lock
/ * * *@authorDay and night of wood */
public class TestC {
/** * One chopstick can only be used by one person at a time (one thread) */
Object chopsticks = new Object();
public static void main(String[] args) {
TestC c = new TestC();
new Thread(()->{
c.eatFish();
}).start();
}
/ * * * * /
public void eatFish( ) {
synchronized (chopsticks) {
try {
System.out.println("Fish");
Thread.sleep(2000);
eatSalad();
} catch (Exception e){ }
}
}
/** * Eat salad */
public void eatSalad(a) {
synchronized (chopsticks) {
try {
System.out.println("Eat salad");
Thread.sleep(2000);
eatFish();
} catch (Exception e){ }
}
}
}
Copy the code
3.5 Underlying Implementation
(1) Simple version of
Synchronized was a heavyweight lock before jdk1.6. Is every lock will go to the operating system to apply for a lock.
Jdk1.6 and later upgrade for locks
The simple idea is:
Synchronized (object)
- Thread A is the first to access
- The bias lock only records the thread ID of thread A in the Markword of object
- If thread A comes in and looks at the thread number of the Markword, it can use it
- And then thread B comes in, and thread B looks at me, right? Someone’s taking the lock!
- Thread B will loop and wait, like knocking on the bathroom door and asking thread A how are you? Knock on the door and ask thread A how are you? Knock on the door and ask thread A how are you? Knock on the door and ask thread A how are you?
- This operation on thread B will be called, in technical terms, a spin lock
- After asking thread B 10 times, it will upgrade to heavyweight lock if it can’t get the lock.
- No lock -> bias lock -> spin lock -> Heavyweight lock
- Lock like.. Upgrade, not downgrade
(2) Complex version
-
CAS brief description to understand the introduction
What is ABA problem, if you have a wife, I say if ~ take stealing pocket money for example
www.processon.com/view/link/6…
This is a story: Xiao Qiang stole pocket money to invite Xiao Ming to dinner story
ABA is:
Xiao Qiang’s wife leaves home with 100,000 yuan (A)
Jack Bauer stole 10,000 yuan and left 90,000 yuan (B)
Xiaoqiang borrows 10,000 yuan from Xiaoyue and puts back 100,000 yuan in total (A)
Xiaoqiang wife came back to see 100 thousand, very satisfied. But what she doesn’t know is that this is a job swap
Then Xiaoqiang’s wife read my blog and found out the secret. What should she do?
Keyword: version Version number
Before she went to work, she wrote a version in pen on her family’s savings, which would change if Jack Bauer stole the money again and returned it (+1).
This solves the ABA problem
-
Locked process
Severe competition: It takes too long to select too many waits
New objects may be anonymously biased directly (if bias locking is turned on by default) because there is no bias to any thread, so it is anonymously biased
The JVM does not enable bias locking by default until a delay of 4 seconds is enabled
-
New What does an object look like?What’s markword
1. View tools: JOL (Java Object Layout)
Direct maven import is ready to use
<dependencies>
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.9</version>
</dependency>
</dependencies>
Copy the code
/ * * *@authorDay and night of wood */
public class Person {
long money;
public long getMoney(a) {
return money;
}
public void setMoney(long money) {
this.money = money; }}/ * * *@authorDay and night of wood */
public class JolTest {
public static void main(String[] args) {
Person p = newPerson(); System.out.println(ClassLayout.parseInstance(p).toPrintable()); }}// Output the result
Person object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00
4 4 (object header) 00 00 00 00
8 4 (object header) 43 c1 00 f8
12 4 (alignment/padding gap)
16 8 long Person.money 0
Instance size: 24 bytes
Space losses: 4 bytes internal + 0 bytes external = 4 bytes total
Copy the code
Yi? I thought it was synchronized?
2. markword
I lock the object p and print layout to see that the markword has changed
So the lock information is recorded in markWord
/ * * *@authorDay and night of wood */
public class JolTest {
public static void main(String[] args) {
Person p = new Person();
System.out.println(ClassLayout.parseInstance(p).toPrintable());
synchronized(p) { System.out.println(ClassLayout.parseInstance(p).toPrintable()); }}}Copy the code
Is MarkWord that good? No! It could be worse. Let’s see what kind of information it contains
First look at the last 3bit other not very understand this time can compare the above layout output take a look
It started with 01 and then changed to 00 (no bias lock switched to lightweight lock)
First, the last 2 bits:
00: Lightweight lock spin lock
Spin locking, which consumes CPU resources, is operated in user mode and is not associated with kernel mode. Two threads compete to put their Lock Record in MarkWord. Who is the first to put the Record in Markword, who is the first to get the Lock, the other person then cas to put the RecordCopy the code
What does a Lock Record point to a markword that is unlocked
So that explains why hashCode doesn’t get lost because there’s a backup record, right
So this is lock reentrant: as mentioned above, lock reentrant, every time the lock goes in, it adds an LR and starting with the second LR it points to a NULL
By the time the lock exits, that is, at Monitorexit, LLR -1, LLR -1 keeps decreasing, decreasing and decreasing
10: Heavyweight lock
This pointer is stored in markWord (Java is an address or ID).
Heavyweight locks, all waiting in a queue, consume less CPU
Reentrant lock: The heavyweight is the record on a property of the Object Moniter
When to upgrade to heavyweight lock:
Before jdk1.6 -xx :PreBlockSpin can adjust the number of updates for more than 10 times. After JDk1.6, adaptive Self Sping is added The JVM controls itselfCopy the code
11:GC collects tags
01: Look at the third from the bottom
001: no lock
101: bias lock thread ID, c++ implementation is used pointer
Synchronized is compiled into bytecode with two words monitorenter monitorexit
When does monitorexit run out of code, or an exception occurs which is how synchronized automatically releases locks
4. Why do you need heavyweight locks when you have spin locks
(1) Spin consumes CPU resources. If the lock time is long or there are many spin threads, THE CPU will be consumed
(2) Heavyweight locks have a wait queue. All those who cannot get the lock enter the wait queue without consuming CPU resources
5. Is bias locking necessarily more efficient than spin locking?
(1) Not necessarily when you know there must be multithreaded contention and biased locking involves lock undo, when spin locking is better
(2) The JVM starts with many threads competing, so bias locking is not enabled by default and will be enabled after some time
(3) – XX: BiasedLockingStartupDelay = 0, the default is 4 seconds
Finally, I attached my wechat official account. I just started to make wishes and make progress together.
Note: the above text only represents personal views, only for reference, if there is a problem, please point out immediately even roll out of bed to correct.