码迷,mamicode.com
首页 > 编程语言 > 详细

Java多线程学习篇(二)synchronized

时间:2018-01-02 23:21:50      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:span   内容   非静态方法   代码   lan   getname   调用   body   void   

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

标签:span   内容   非静态方法   代码   lan   getname   调用   body   void   

原文地址:https://www.cnblogs.com/lkcc/p/8178963.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!