Java多线程同步synchronized

原创 2018年04月17日 11:40:51

synchronized

每一个用synchronized关键字声明的方法都是临界区。在Java中,同一个对象的临界区,在同一时间只有一个允许被访问。当一个线程试图访问一个临界区时,它将使用一种同步机制来查看是不是已有其他线程进入临界区。如果没有其他线程进入临界区,它就可以进入临界区;如果已有线程进入了临界区,它就被同步机制挂起,直到进入的线程离开这个临界区。如果在等待进入临界区的线程不止一个,JVM会随机选择其中的一个,其余的将继续等待。

使用方式

1、synchronized方法

    public synchronized void method() {
         //代码
    }

修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁

修饰静态方法,作用于当前类对象加锁,进入同步代码前要获得当前类对象的锁

2、synchronized代码块

synchronized(obj)  
{  
    //代码块  
}  

其中可将synchronized作用于一个给定的实例对象obj,每次当线程进入synchronized包裹的代码块时就会要求当前线程持有obj实例对象锁,如果当前有其他线程正持有该对象锁,那么新到的线程就必须等待,同时也可以使用this对象,代表当前实例,相当于synchronized修饰实例方法,或者当前类的class对象作为锁,相当于synchronized修饰静态方法。

以下是一个验证synchronized静态方法与synchronized代码块使用类锁获取的是同一把锁的例子:

public class TestSynchronizedMethod {

    // 方法1-synchronized块(对象级)
    public void method1() {
        synchronized (this) {
            try {
                for (int i = 0; i < 10; i++) {
                    Thread.sleep(100);
                    System.out.println(Thread.currentThread().getName()+" synchronized块(对象级)");
                }
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    // 方法2-synchronized块(类级别)
    public void method2() {
        synchronized (TestSynchronizedMethod.class) {
            try {
                for (int i = 0; i < 10; i++) {
                    Thread.sleep(100);
                    System.out.println(Thread.currentThread().getName()+" synchronized块(类级别)");
                }
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    // 方法3-synchronized 普通方法
    public synchronized void method3() {
        try {
            for (int i = 0; i < 10; i++) {
                Thread.sleep(100);
                System.out.println(Thread.currentThread().getName()+" synchronized普通方法");
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    // 方法4-synchronized 静态方法
    public static synchronized void method4() {
        try {
            for (int i = 0; i < 10; i++) {
                Thread.sleep(100);
                System.out.println(Thread.currentThread().getName()+" synchronized静态方法");
            }
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
public class TestThread implements Runnable {

    private TestSynchronizedMethod syncT;
    private int method;

    public TestThread(TestSynchronizedMethod syncT, int method) {
        this.syncT = syncT;
        this.method = method;
    }

    @Override
    public void run() {
        if (method == 1)
            syncT.method1();
        if (method == 2)
            syncT.method2();
        if (method == 3)
            syncT.method3();
        if (method == 4)
            syncT.method4();
    }

}
public class TestMain {

    public static void main(String[] args) throws InterruptedException {
        TestSynchronizedMethod tsm = new TestSynchronizedMethod();
        TestSynchronizedMethod tsm2 = new TestSynchronizedMethod();
        TestThread test1 = new TestThread(tsm,2);
        TestThread test2 = new TestThread(tsm,4);
        Thread temp1 = new Thread(test1, "thread1");
        Thread temp2 = new Thread(test2, "thread2");
        temp1.start();
        temp2.start();
    }
}

执行结果如下,thread2在thread1执行结束之后才会执行,同时可以改变main方法中的参数来验证其他结果。

thread1 synchronized块(类级别)
thread1 synchronized块(类级别)
thread1 synchronized块(类级别)
thread1 synchronized块(类级别)
thread1 synchronized块(类级别)
thread1 synchronized块(类级别)
thread1 synchronized块(类级别)
thread1 synchronized块(类级别)
thread1 synchronized块(类级别)
thread1 synchronized块(类级别)
thread2 synchronized静态方法
thread2 synchronized静态方法
thread2 synchronized静态方法
thread2 synchronized静态方法
thread2 synchronized静态方法
thread2 synchronized静态方法
thread2 synchronized静态方法
thread2 synchronized静态方法
thread2 synchronized静态方法
thread2 synchronized静态方法

#Point

用synchronized关键字声明的静态方法,同时只能被一个执行线程访问,但是其他线程可以访问这个对象的非静态方法。即:两个线程可以同时访问一个对象的两个不同的synchronized方法,其中一个是静态方法,一个是非静态方法。原因在于它们获取的锁不同,一个获取的是当前对象的锁,另一个获取的是类锁。

synchronized关键字不能继承

在定义接口方法时不能使用synchronized关键字。

构造方法不能使用synchronized关键字,但可以使用synchronized代码块来进行同步。

版权声明:本文为博主原创文章,未经博主允许请随便转载。 https://blog.csdn.net/lazyRabbitLLL/article/details/79970628

我们该为千疮百孔的NT作些什么????

如何配置一台NT对大家来说不是一件很困难的事,可是要配置一台安全性高的NT可就不那么容易了,作为一个好的系统管理人员,一定要学会怎么让你手中的NT 4达到真正的C2级。&#61548; 最重要的一点,...
  • ghj1976
  • ghj1976
  • 2000-08-31 10:10:00
  • 1363

java 多线程 同步详解

  • 2013年09月22日 15:25
  • 24KB
  • 下载

Java多线程:线程同步与关键字synchronized

一、同步的特性 1. 不必同步类中所有的方法, 类可以同时拥有同步和非同步方法. 2. 如果线程拥有同步和非同步方法, 则非同步方法可以被多个线程自由访问而不受锁的限制. 参见实验1: htt...
  • huang_xw
  • huang_xw
  • 2012-03-04 19:08:11
  • 6034

【转】简单计数器以及synchronized 关键字

当一个方法有synchronized来修饰时,如果遇到多个客户端要同时访问这个方法的时候,就会进行同步处理,让各个客户端串行地访问同一段代码...WEB程序可能有并发的多个用户同时访问.中定义的变量是...
  • xiangliling
  • xiangliling
  • 2012-10-22 11:00:13
  • 294

Java 内部类,多线程中Synchronized与wait,notify的使用

工作内容: 1.成员内部类    与成员方法,属性的访问权限一致 2.静态内部类    修饰符 stactic 类名{...} 3.匿名内部类    new 类名()/接口名(重写接口方法) 4.局...
  • yingtian648
  • yingtian648
  • 2016-07-22 08:59:17
  • 583

Java多线程,线程同步synchronized,线程死锁【线程池常规用法】多线程并发处理

工作内容: 1.线程同步:synchronized (锁类) 2.线程死锁 3.生产者与消费者模式 4.线程练习 线程同步: Synchronized(Object){ 代码块 } Public ...
  • yingtian648
  • yingtian648
  • 2016-07-14 09:01:19
  • 454

Java之多线程内存可见性_2(synchronized可见性原理)

可见性: 要实现共享变量的可见性,必须保证2点: 1.线程修改后的共享变量值能够及时从工作内存刷新到主内存中。 2.其他线程能够及时把共享变量的最新值从主内存更新到自己的工作内存中。 以下的记录都是来...
  • u014293922
  • u014293922
  • 2015-12-17 11:29:45
  • 779

Java线程同步的解决方案——synchronized与Lock

要说明线程同步问题首先要说明Java线程的两个特性,可见性和有序性。多个线程之间是不能直接传递数据交互的,它们之间的交互只能通过共享变量来实现。例如,假设在多个线程之间共享了Count类的一个对象,C...
  • fuzhongmin05
  • fuzhongmin05
  • 2017-03-19 12:26:15
  • 699

synchronized、锁、多线程同步的原理是咋样

先综述个结论: 一般说的synchronized用来做多线程同步功能,其实synchronized只是提供多线程互斥,而对象的wait()和notify()方法才提供线程的同步功能。 ...
  • jks456
  • jks456
  • 2016-03-05 21:54:27
  • 2738

Java线程同步 (synchronized wait notify)

注:wait notify 都是Object的方法 同步(阻塞) :是一种防止对共享资源访问导致的数据不一致的一种模式。详细请参看操作系统。在Java中,由于对多线程的支持,对同步的控制主要通过以下几...
  • weizhaozhe
  • weizhaozhe
  • 2009-02-22 17:46:00
  • 52338
收藏助手
不良信息举报
您举报文章:Java多线程同步synchronized
举报原因:
原因补充:

(最多只允许输入30个字)