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

1.引言

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

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

    共享资源通常是以对象形式存在的内存片断,但也能够是文件、输入/输出端口,或者是打印机设备。要控制对共享资源的访问,得先把它包装进一个对象。而后把全部要访问这个资源的方法标记为synchronized。若是某个任务处于一个对标记为synchronized方法的调用中,那么在这个线程从该方法返回以前,其余全部要调用类中任何标记synchronized方法的线程都会被阻塞。多线程

2.synchronized原理

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

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

3.synchronized基本用法

    synchronized语句计算一个对象引用,试图对该对象完成锁操做,而且在完成所操做前中止处理。当锁操做完成,synchronized语句体获得执行。当语句体执行完毕(不管正常与否),解锁操做自动执行。synchronized常常与方法连用。函数

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

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

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

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

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();
   } 
}

运行结果:spa

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

结果说明:.net

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修饰。

相关文章
相关标签/搜索