第一周:理解Java中的Synchronized关键字

指标:理解Synchronized的含义,明确Synchronized关键字修饰普通方法、静态方法和代码块时锁对象的差异

1、含义:Synchronized是Java中解决并发问题的一种最常见的方法,也是最简单的一种方法。用于处理多线程中访问相同资源造成冲突的一种同步锁,实现代码的中的同步机制。
2、作用:主要有三个作用
①确保线程互斥的访问同步代码块
②保证共享变量的修改能够及时可见
③有效解决重排序问题
3、修饰对象
①修饰普通方法,其作用范围是整个方法,作用的对象是调用这个方法的对象。

②修饰静态方法,其作用范围是这个静态方法,作用对象是这个类的所有对象

③修饰代码块,其作用范围是由{}括起来的代码块,作用的对象是调用这个代码块的对象

一个线程访问一个对象中的synchronize同步代码块时,试图访问该对象的线程将被阻塞

class SyncThread implements Runnable {
    private static int count;

    public SyncThread() {
        count = 0;
    }

    public void run() {
        synchronized (this) {
            for (int i = 0; i < 5; i++) {
                try {
                    System.out.println(Thread.currentThread().getName() + ":" + (count++));
                    Thread.sleep(100);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

    }

    public int getCount() {
        return count;
    }
}

public class test {
    public static void main(String[] args) {

        SyncThread syncThread = new SyncThread();
        Thread thread1 = new Thread(syncThread, "sycn1");
        Thread thread2 = new Thread(syncThread, "sycn2");
        thread1.start();
        thread2.start();

    }


}

上面的代码在控制台打印时依次等待执行,结果如下

sycn1:0
sycn1:1
sycn1:2
sycn1:3
sycn1:4
sycn2:5
sycn2:6
sycn2:7
sycn2:8
sycn2:9

当两个并发线程(thread1和thread2)访问同一个对象(syncThread)中的synchronized代码块时,在同一时刻只能有一个线程得到执行,另一个线程受阻塞,必须等待当前线程执行完这个代码块以后才能执行该代码块。Thread1和thread2是互斥的,因为在执行synchronized代码块时会锁定当前的对象,只有执行完该代码块才能释放该对象锁,下一个线程才能执行并锁定该对象

我们把SyncThread的调用修改如下:

        Thread thread1 = new Thread(new SyncThread(), "sycn1");
        Thread thread2 = new Thread(new SyncThread(), "sycn2");
        thread1.start();
        thread2.start();

执行结果如下:

sycn1:0
sycn2:1
sycn1:2
sycn2:3
sycn2:5
sycn1:4
sycn2:6
sycn1:6
sycn1:8
sycn2:7

不是说一个线程执行synchronized代码块时其它的线程受阻塞吗?为什么上面的例子中thread1和thread2同时在执行?
这是因为synchronized只锁定对象,每个对象只有一个锁(lock)与之相关联,而上面的代码等同于下面这段代码:

SyncThread syncThread1 = new SyncThread();
SyncThread syncThread2 = new SyncThread();
Thread thread1 = new Thread(syncThread1, "SyncThread1");
Thread thread2 = new Thread(syncThread2, "SyncThread2");
thread1.start();
thread2.start();

这时创建了两个SyncThread的对象syncThread1和syncThread2,线程thread1执行的是syncThread1对象中的synchronized代码(run),而线程thread2执行的是syncThread2对象中的synchronized代码(run);我们知道synchronized锁定的是对象,这时会有两把锁分别锁定syncThread1对象和syncThread2对象,而这两把锁是互不干扰的,不形成互斥,所以两个线程可以同时执行

问题答案:
问题1:不同步,因为a1.a和a2.a不是同一个锁,锁住的是this
问题2:同步,因为关键字static已经让这个代码块都添加上了同一把锁,锁住的是this.class

你可能感兴趣的:(第一周:理解Java中的Synchronized关键字)