Java多线程学习篇synchronized

Posted 黑.白

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java多线程学习篇synchronized相关的知识,希望对你有一定的参考价值。

synchronized 有二种修饰方法:
  1. 修饰一个方法

    synchronized public void runTest{
        /**/
    }
  2. 修饰一个代码块

    public void runTest{
        synchronized( /*某一对象或某一类*/ ){
            /* 代码块 */
        }
    }
synchronized 的作用范围分为修饰一个类和修饰一共对象
当修饰一个对象时,不同线程的同一对象调用相同代码会发生堵塞
当修饰一个时,不同线程的同一类调用相同代码会发生堵塞
修饰静态方法相当于修饰类

定义一个类(用于验证 synchronized 的作用范围)

public class Test implements Runnable {

    public static int Count = 0;

    @Override
    public void run() {
        runTest();
    }

    public void runTest() {
        for (int i = 0; i < 5; ++i) {
            Count++;
            System.out.println(Thread.currentThread().getName() + " " + Count);
        }
    }
}

当 synchronized 修饰一个方法时

  1. 若方法为非静态方法,作用的范围是一个对象

    不同线程的同一对象调用该方法时会发生堵塞

    //调用相同的对象
    synchronized public void runTest() { // 修饰非静态的方法 for (int i = 0; i < 5; ++i) { Count++; System.out.println(Thread.currentThread().getName() + " " + Count); } }

    通过以下代码调用

    Test test = new Test();
    Thread thread_one = new Thread( test, "Thread_ONE" );
    Thread thread_two = new Thread( test, "Thread_Two" );
    thread_one.start();
    thread_two.start();

    结果是

    Thread_ONE 1
    Thread_ONE 2
    Thread_ONE 3
    Thread_ONE 4
    Thread_ONE 5
    Thread_Two 6
    Thread_Two 7
    Thread_Two 8
    Thread_Two 9
    Thread_Two 10

    由于该调用是二个thread任务中的对象是同一个test,第一个thread任务运行时,会将第二个任务堵塞

    若对象不是同一个,则不会发生堵塞

    //调用二个不同的对象
    Thread thread_one = new Thread(new Test(), "Thread_ONE");
    Thread thread_two = new Thread(new Test(), "Thread_Two");
    thread_one.start();
    thread_two.start();

    结果是

    Thread_Two 2
    Thread_ONE 1
    Thread_Two 3
    Thread_ONE 4
    Thread_Two 5
    Thread_ONE 6
    Thread_Two 7
    Thread_ONE 8
    Thread_Two 9
    Thread_ONE 10

     

  2.  当修饰的方法为静态的方法时,作用的范围是一个类,而非一个对象。

    不同线程的相同类调用该方法时都会发生堵塞

    //调用相同的对象
    Test test = new Test();
    Thread thread_one = new Thread( test, "Thread_ONE" );
    Thread thread_two = new Thread( test, "Thread_Two" );
    thread_one.start();
    thread_two.start();
    
    //调用二个不同的对象
    Thread thread_one = new Thread(new Test(), "Thread_ONE");
    Thread thread_two = new Thread(new Test(), "Thread_Two");
    thread_one.start();
    thread_two.start();

    结果都为

    Thread_ONE 1
    Thread_ONE 2
    Thread_ONE 3
    Thread_ONE 4
    Thread_ONE 5
    Thread_Two 6
    Thread_Two 7
    Thread_Two 8
    Thread_Two 9
    Thread_Two 10

 

当 synchronized 修饰一个代码块时,作用的范围看括号内的内容。若括号内为对象,则范围是一个对象;若括号内为类,则范围是一个类

  1. 若括号内为对象,则范围是一个对象,效果和 synchronized 修饰非静态方法一样

    public void runTest() {
        synchronized (this) { // 括号内为一个对象
            for (int i = 0; i < 5; ++i) {
                Count++;
                System.out.println(Thread.currentThread().getName() + " " + Count);
            }
        }
    }

    效果

    //调用相同的对象
    Test test = new Test();
    Thread thread_one = new Thread( test, "Thread_ONE" );
    Thread thread_two = new Thread( test, "Thread_Two" );
    thread_one.start();
    thread_two.start();
    //发生类堵塞
    //Thread_ONE 1
    //Thread_ONE 2
    //Thread_ONE 3
    //Thread_ONE 4
    //Thread_ONE 5
    //Thread_Two 6
    //Thread_Two 7
    //Thread_Two 8
    //Thread_Two 9
    //Thread_Two 10
    
    
    //调用二个不同的对象
    Thread thread_one = new Thread(new Test(), "Thread_ONE");
    Thread thread_two = new Thread(new Test(), "Thread_Two");
    thread_one.start();
    thread_two.start();
    // 没有发生堵塞
    //Thread_Two 2
    //Thread_ONE 1
    //Thread_Two 3
    //Thread_ONE 4
    //Thread_Two 5
    //Thread_ONE 6
    //Thread_Two 7
    //Thread_ONE 8
    //Thread_Two 9
    //Thread_ONE 10
  2.  若括号内为类,则范围是一个对象,效果和 synchronized 修饰静态方法一样

    public [static] void runTest() {  
        synchronized (Test.class) { // 括号内为一个类
            for (int i = 0; i < 5; ++i) {
                Count++;
                System.out.println(Thread.currentThread().getName() + " " + Count);
            }
        }
    }

    二种调用都发生堵塞 

    Thread_ONE 1
    Thread_ONE 2
    Thread_ONE 3
    Thread_ONE 4
    Thread_ONE 5
    Thread_Two 6
    Thread_Two 7
    Thread_Two 8
    Thread_Two 9
    Thread_Two 10

 参考:http://tutorials.jenkov.com/java-concurrency/synchronized.html





以上是关于Java多线程学习篇synchronized的主要内容,如果未能解决你的问题,请参考以下文章

Java多线程系列---“基础篇”04之 synchronized关键字

java多线程中synchronize锁的使用和学习,Thread多线程学习

Synchronized详解

java 多线程系列基础篇之 synchronized关键字

[ 转载 ] Java多线程系列--“基础篇”04之 synchronized关键字

多线程学习(基础篇)