Java高并发 Synchronized详解(一)

释放双眼,带上耳机,听听看~!

1.1、Synchronized的作用

同步方法支持一种简单的策略来防止线程干扰和内存一致性错误:如果一个对象对多个线程可见,则对该对象变量的所有读取或者写入都是通过同步方法完成的。
能够保证在同一时刻最多只有一个线程执行该段代码,以达到保证并发安全的效果。

2.2、Synchronized的地位

Synchronized是Java的关键字,被Java语言原生支持。
是最基本的互斥同步手段。
是并发编程中的元老级角色,是并发编程的必学内容。

2.3、两线程同时a++


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1package disappear.request;
2public class disappear1 implements Runnable{
3    static disappear1 instant = new disappear1();
4    static int i = 0;
5    public static void main(String [] args) throws InterruptedException {
6        Thread t1 = new Thread(instant);
7        Thread t2 = new Thread(instant);
8        t1.start();
9        t2.start();
10        t1.join();
11        t2.join();
12        System.out.println(i);
13    }
14    @Override
15    public void run() {
16        for(int j=0;j<100000;j++){
17            i++;
18        }
19    }
20}
21
22

最后得出的结果会比预期的小;
原因: i++ 实际包含的三个动作。
1、读取 i ;
2、将 i 加一 ;
3、将 i 的值写入内存。
线程 t1 将 i 加一,还没有写入内存时,线程 t2 也进行了加一操作 , 两线程在将 i 的值写入内存,发生了线程不安全。

2.4、Synchronized 的两种用法

2.4.1、对象锁
包括 方法锁(默认锁 是this的当前实例对象)和 同步代码块锁 (自己指定锁的对象)

1、代码块形式:手动指定锁对象


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
1package disappear.request;
2
3public class SynchronizedObjectCodeBlock2 implements Runnable{
4    static SynchronizedObjectCodeBlock2 instent = new SynchronizedObjectCodeBlock2();
5    Object lock1 = new Object();
6    Object lock2 = new Object();
7    @Override
8    public void run() {
9        synchronized (lock1){
10            System.out.println("My name is:"+Thread.currentThread().getName()+" catch lock1");
11            try {
12                Thread.sleep(3000);
13            } catch (InterruptedException e) {
14                e.printStackTrace();
15            }
16            System.out.println(Thread.currentThread().getName()+" is over! throw lock1");
17        }
18        synchronized (lock2){
19            System.out.println("My name is:"+Thread.currentThread().getName()+"catch lock2");
20            try {
21                Thread.sleep(3000);
22            } catch (InterruptedException e) {
23                e.printStackTrace();
24            }
25            System.out.println(Thread.currentThread().getName()+" is over! throw lock2");
26        }
27    }
28
29    public static void  main(String [] args) throws InterruptedException {
30        Thread t1 = new Thread(instent);
31        Thread t2 = new Thread(instent);
32        t1.start();
33        t2.start();
34        while(t1.isAlive() || t2.isAlive()){
35        }
36        System.out.println("Over!");
37    }
38}
39
40

打印结果:

My name is:Thread-0 catch lock1
Thread-0 is over! throw lock1
My name is:Thread-0catch lock2
My name is:Thread-1 catch lock1
Thread-0 is over! throw lock2
Thread-1 is over! throw lock1
My name is:Thread-1catch lock2
Thread-1 is over! throw lock2
Over!

2、方法锁形式:synchronized修饰普通方法,锁对象默认为this


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1package disappear.request;
2
3public class SynchronizedObjectMethod3 implements Runnable{
4    static SynchronizedObjectMethod3 instence = new SynchronizedObjectMethod3();
5    @Override
6    public void run() {
7            Method();
8    }
9    public synchronized void Method() {
10        System.out.println("My name is :"+Thread.currentThread().getName());
11        try{
12            Thread.sleep(3000);
13        }catch(InterruptedException ie){
14            ie.printStackTrace();
15        }
16        System.out.println(Thread.currentThread().getName()+" is over!");
17    }
18    public static void main(String [] args){
19        Thread t1 = new Thread(instence);
20        Thread t2 = new Thread(instence);
21        t1.start();
22        t2.start();
23        while(t1.isAlive()||t2.isAlive()){
24
25        }
26        System.out.println("Over!");
27    }
28}
29
30

My name is :Thread-0
Thread-0 is over!
My name is :Thread-1
Thread-1 is over!
Over!

方法锁形式synchronized 修饰普通方法,默认的锁对象是this;

2.4.2、类锁
指synchronized修饰 静态 方法或指定锁为 Class对象
概念:Java类可能有很多个对象,但是只有一个Class对象。
本质:所谓类锁,是将 Class对象 作为锁。
用法和效果:类锁只能在同一时刻被一个对象拥有。

形式1:synchronized 加在 static 方法上。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
1package disappear.request;
2
3public class SynchronizedsClassStatic4 implements Runnable{
4    static SynchronizedsClassStatic4 instence1 = new SynchronizedsClassStatic4();
5    static SynchronizedsClassStatic4 instence2 = new SynchronizedsClassStatic4();
6    //在全局上进行方法的保护
7    public static synchronized void Method(){
8        System.out.println("My name is:"+Thread.currentThread().getName());
9        try{
10            Thread.sleep(3000);
11        }catch(InterruptedException ie){
12            ie.printStackTrace();
13        }
14        System.out.println(Thread.currentThread().getName()+"is over!");
15    }
16    @Override
17    public void run() {
18        Method();
19    }
20    public static void main(String[] args){
21        Thread t1 = new Thread(instence1);
22        Thread t2 = new Thread(instence2);
23        t1.start();
24        t2.start();
25        while(t1.isAlive()||t2.isAlive()){
26
27        }
28        System.out.println("All is Over!");
29    }
30}
31
32

//串行运行
My name is:Thread-0
Thread-0is over!
My name is:Thread-1
Thread-1is over!
All is Over!

形式2:synchronized ( *.class ) 代码块


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
1package disappear.request;
2
3public class SynchronizedClassClass5 implements Runnable{
4    static SynchronizedClassClass5 instence1 = new SynchronizedClassClass5();
5    static SynchronizedClassClass5 instence2 = new SynchronizedClassClass5();
6    private void Method(){
7        //无论创建的是哪一个实例,运用的都是同一个对象.
8        synchronized (SynchronizedClassClass5.class){
9            System.out.println("My name is:"+Thread.currentThread().getName());
10            try{
11                Thread.sleep(3000);
12            }catch(InterruptedException ie){
13                ie.printStackTrace();
14            }
15            System.out.println(Thread.currentThread().getName()+" is over!");
16        }
17    }
18    @Override
19    public void run() {
20        Method();
21    }
22    public static void main(String [] args){
23        Thread t1 = new Thread(instence1);
24        Thread t2 = new Thread(instence2);
25        t1.start();
26        t2.start();
27        while(t1.isAlive()||t2.isAlive()){
28
29        }
30        System.out.println("All is Over!");
31    }
32}
33
34

输出结果:串行输出

My name is:Thread-0
Thread-0 is over!
My name is:Thread-1
Thread-1 is over!
All is Over!

2.5、解决 i++ 问题


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
1//synchronized修饰代码块。
2package disappear.request;
3
4public class disappear1 implements Runnable{
5    static disappear1 instant = new disappear1();
6    static int i = 0;
7    public static void main(String [] args) throws InterruptedException {
8        Thread t1 = new Thread(instant);
9        Thread t2 = new Thread(instant);
10        t1.start();
11        t2.start();
12        t1.join();
13        t2.join();
14        System.out.println(i);
15    }
16    @Override
17    public void run() {
18       synchronized (this){
19           for(int j = 0;j<100000;j++){
20               i++;
21           }
22       }
23    }
24}
25
26

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
1//synchronized修饰对象方法。
2package disappear.request;
3
4public class disappear1 implements Runnable{
5    static disappear1 instant = new disappear1();
6    static int i = 0;
7    public static void main(String [] args) throws InterruptedException {
8        Thread t1 = new Thread(instant);
9        Thread t2 = new Thread(instant);
10        t1.start();
11        t2.start();
12        t1.join();
13        t2.join();
14        System.out.println(i);
15    }
16    public synchronized void method(){
17        for(int j = 0;j<100000;j++){
18            i++;
19        }
20    }
21    @Override
22    public void run() {
23        method();
24    }
25}
26
27
28

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
1//类锁,将一个类对象.class,作为synchronized的锁;
2package disappear.request;
3
4public class disappear1 implements Runnable{
5    static disappear1 instant = new disappear1();
6    static int i = 0;
7    public static void main(String [] args) throws InterruptedException {
8        Thread t1 = new Thread(instant);
9        Thread t2 = new Thread(instant);
10        t1.start();
11        t2.start();
12        t1.join();
13        t2.join();
14        System.out.println(i);
15    }
16    public synchronized void Method(){
17        synchronized (disappear1.class){
18            for(int j = 0;j<100000;j++){
19                i++;
20            }
21        }
22    }
23    @Override
24    public void run() {
25        Method();
26    }
27}
28
29
30

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
1//静态方法 加上synchronized关键字达到的效果
2package disappear.request;
3
4public class disappear1 implements Runnable{
5    static disappear1 instant = new disappear1();
6    static int i = 0;
7    public static void main(String [] args) throws InterruptedException {
8        Thread t1 = new Thread(instant);
9        Thread t2 = new Thread(instant);
10        t1.start();
11        t2.start();
12        t1.join();
13        t2.join();
14        System.out.println(i);
15    }
16    public static synchronized void Method(){
17            for(int j = 0;j<100000;j++){
18                i++;
19            }
20    }
21    @Override
22    public void run() {
23        Method();
24    }
25}
26
27
28

给TA打赏
共{{data.count}}人
人已打赏
安全经验

Google Adsense的技巧、诀窍和秘密

2021-10-11 16:36:11

安全经验

安全咨询服务

2022-1-12 14:11:49

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索