Java学习系列文章第一篇:Java中Synchronized的用法

由于本人正在从PHP转向Java,在学习Java的过程中,加深自己的印象和为了更深层的理解,于是乎有了写这系列的文章,本文是系列的第一篇。
本文讲的是Java中的synchronized关键字,它是一种同步锁。它可以修饰的对象有一下几种:

  1. 修饰一个代码块,被修饰的代码块中称为同步语句块,作用的范围是大括号{}内的代码,作用的对象是调用这个代码块的对象。
  2. 修饰一个方法,被修饰的方法称为同步方法,作用的范围是整个方法,作用的对象是调用这个方法的对象。
  3. 修饰一个静态方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象。
  4. 修饰一个类,其作用的范围是synchronized后面括号括起来的部分,作用的对象是这个类的所有对象。
  • 修饰一个代码块

1.一个线程访问一个对象中的synchronized(this)同步代码块时,其他线程不能访问此处代码。我们看下面的例子:

public class MyThread1 implements Runnable {

    private static int count = 0;

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

    public static void main(String[] args){
        MyThread1 myThread1 = new MyThread1(); 
        Thread thread1 = new Thread(myThread1, "myThread1");
        Thread thread2 = new Thread(myThread1, "myThread2");
        thread1.start();
        thread2.start();
    }

}

程序输出结果如下:

myThread1:0
myThread1:1
myThread1:2
myThread1:3
myThread1:4
myThread2:5
myThread2:6
myThread2:7
myThread2:8
myThread2:9

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

Thread thread1 = new Thread(new MyThread1(), "myThread1");
Thread thread2 = new Thread(new MyThread1(), "myThread2");
thread1.start();
thread2.start();

程序的执行结果如下:

myThread2:0
myThread1:1
myThread2:2
myThread1:2
myThread2:3
myThread1:4
myThread2:5
myThread1:6
myThread2:7
myThread1:8

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

MyThread1 myThread1 = new MyThread1(); 
MyThread1 myThread2 = new MyThread1();

Thread thread1 = new Thread(myThread1, "myThread1");
Thread thread2 = new Thread(myThread2, "myThread2");
thread1.start();
thread2.start();

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

2.当一个线程访问对象的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该对象中的非synchronized(this)同步代码块。

未完,待续……

相关文章

此处评论已关闭