Java基础之synchronized同步的使用

0、有关多线程的实现先参考:Java基础之多线程的基本实现
1、两个线程访问同一个对象,如果没有同步的限制,会出现一个意想不同的问题;
2、比如对象成员属性int i = 100;某方法每执行一次都会对该值进行减1操作,直接为0结束;
3、单次调用的基本流程应该是:start->{body}->end;但从start到end这个过程是需要时间的;
4、假设是完整过程是A->B->C,如果两个线程同时执行则会出现A调用还未结束B即开始调用;
5、理想的过程是A1->B1->C1->A2->B2->C2->A3->B3->C3,两个线程一起来则会出现A1->A2->B1->C1->B2->C2;
6、为了保证A->B->C这三步能不被中断,完整地一个一个执行,则需要对A->B->C进行加锁保护;
7、加锁保护即使之同步,使开始A就到C之后再重新开启一个新过程;
8、代码块需要加锁则使用修饰词synchronized(){}将代码包含在大括号内;
9、整个方法需要加锁则在方法修饰词中加synchronized关键字
参考代码:

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
41
42
class Demo{
	public static void main(String [] args){
		// 创建一个Service对象,使两个线程同时对该对象进行操作
		Service service = new Service();
		// 线程1访问Service对象的第一个方法,因为同步方法,service对象会被锁定
		Thread thread1 = new Thread(new Runnable(){
			public void run(){
				service.fun1();
			}
		});
		// 线程2访问Service对象的第二个方法
		// 由于第二个方法包含synchronized修饰
		// 并且同步加锁的是service对象本身;
		// 所以线程2只能等待service解锁后才能执行
		Thread thread2 = new Thread(new Runnable(){
			public void run(){
				service.fun2();
			}
		});
		thread1.start();
		thread2.start();
	}
 
}
// 同步方法的两种写法
class Service{
	// 1、在方法修饰词前加synchronized
	public synchronized void fun1(){
		try{
			Thread.sleep(3000);
		}catch(Exception e){
			System.out.println(e);
		}
		System.out.println("fun1");
	}
	// 2、在代码块中加synchronized(){}来修饰
	public void fun2(){
		synchronized(this){
			System.out.println("fun2");
		}
	}
}

运行结果:
fun1
fun2
说明线程2在等待线程1结束后才执行,如果将方法fun2里的synchronized修饰词去掉则线程2会先执行完!

Leave a Reply