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