您的位置:首页 > 编程语言 > Java开发

Java多线程基础篇(03)-synchronized关键字

2016-09-20 00:00 429 查看
摘要: Java以提供关键字synchronized的形式,为防止资源冲突提供了内置支持。当任务要执行被synchronized关键字保护的代码片段的时候,它将检查锁是否可用,然后获取锁,执行代码,释放锁

1.引言

基本上所有的并发模式再解决线程冲突的时候,都是采用序列化访问共享资源的方案。这意味着在给定时刻只允许一个任务访问共享资源。通常这是通过在代码前面添加一条锁语句来实现的,这就使得在一段时间内只有一个任务可以运行这段代码。因为锁语句产生了一种互相排斥的效果,锁着这种机制常常被称为互斥量。

Java以提供关键字synchronized的形式,为防止资源冲突提供了内置支持。当任务要执行被synchronized关键字保护的代码片段的时候,它将检查锁是否可用,然后获取锁,执行代码,释放锁

共享资源一般是以对象形式存在的内存片段,但也可以是文件、输入/输出端口,或者是打印机设备。要控制对共享资源的访问,得先把它包装进一个对象。然后把所有要访问这个资源的方法标记为synchronized。如果某个任务处于一个对标记为synchronized方法的调用中,那么在这个线程从该方法返回之前,其他所有要调用类中任何标记synchronized方法的线程都会被阻塞。

2.synchronized原理

在Java中,每一个对象有且仅有一个同步锁。这也意味着,同步锁依赖对象而存在。当我们调用某个对象的synchronized修饰的方法时,就获取了该对象的同步锁。例如synchronized(obj)方法就获取了obj这个对象的同步锁。

不同线程对同步锁的访问是互斥的。也就是说,在某一个时刻,对象的同步锁只能被一个线程获取到!其他要获取该锁的线程都会被阻塞。知道线程释放了该锁,其他线程才能去获取同步锁,然后执行代码块。详细的synchronized工作原理请见博客:synchronized实现原理

3.synchronized基本用法

synchronized语句计算一个对象引用,试图对该对象完成锁操作,并且在完成所操作前停止处理。当锁操作完成,synchronized语句体得到执行。当语句体执行完毕(无论正常与否),解锁操作自动执行。synchronized经常与方法连用。

public synchronized void function(){
//保护函数
}

一种比较好的办法是,如果某个变量由一个线程赋值,并由别的线程引用或赋值,那么所有对该变量的访问都必须在某个synchronized语句或者synchronized方法内,

synchronized(this){
//保护代码块
}

有了synchronized关键字,多线程程序的运行结果将变得可以控制。synchronized关键字用于保护共享数据。所以编程时分清共享数据很重要。

4.synchronized代码演示

4.1 synchronized为对象实例加锁

class MyRunable implements Runnable {

@Override
public void run() {
synchronized(this) {
try {
for (int i = 0; i < 5; i++) {
Thread.sleep(100); // 休眠100ms
System.out.println(Thread.currentThread().getName() + " loop " + i);
}
} catch (InterruptedException ie) {
}
}
}
}

public class Demo1_1 {

public static void main(String[] args) {
Runnable demo = new MyRunable();
Thread t1 = new Thread(demo, "t1");
Thread t2 = new Thread(demo, "t2");
t1.start();
t2.start();
}
}

运行结果:

t1 loop 0
t1 loop 1
t1 loop 2
t1 loop 3
t1 loop 4
t2 loop 0
t2 loop 1
t2 loop 2
t2 loop 3
t2 loop 4

结果说明:

run()方法中存在synchronized(this)代码块,而且t1和t2都是基于Runnable对象创建的线程。这就意味着,我们可以将synchronized(this)中的this看作是Runnable对象;因此t1和t2共享demo对象的同步锁。所以,当一个线程运行的时候,另外一个线程必须等待“运行中的线程”释放同步锁之后才能运行。特此说明:synchronized(this)中的this是指当前的类对象,即synchronized(this)所在的类对应的当前对象。它的作用是获取“当前对象的同步锁”。

4.2 synchronized为方法加锁

synchronized方法是用synchronized修饰的方法,具体示例这里不给出了,有兴趣的童鞋,可以参照4.1给方法加上synchronized修饰。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  java synchronized 同步