Java同步之synchronized
来源:互联网 发布:centos 安装mysql5.7 编辑:程序博客网 时间:2024/05/23 10:12
Java中可以使用关键字synchronized进行线程同步控制,实现关键资源顺序访问,避免由于多线程并发执行导致的数据不一致性等问题。synchronized的原理是对象监视器(锁),只有获取到监视器的线程才能继续执行,否则线程会等待获取监视器。Java中每个对象或者类都有一把锁与之相关联,对于对象来说,监视的是这个对象的实例变量,对于类来说,监视的是类变量(一个类本身是类Class的对象,所以与类关联的锁也是对象锁)。synchronized关键字使用方式有两种:synchronized方法和synchronized块。这两种监视区域都和一个引入对象相关联,当到达这个监视区域时,JVM就会锁住这个引用对象,当离开时会释放这个引用对象上的锁(有异常退出时,JVM会释放锁)。对象锁是JVM内部机制,只需要编写同步方法或者同步块即可,操作监视区域时JVM会自动获取锁或者释放锁。
运行该程序输出结果为:可以看到testSynchronizedMethod方法在两个线程之间同步执行。
如果此时将main方法修改为如下所示,则两个线程并不能同步执行,因为此时两个线程的同步监视器不是同一个对象,不能起到同步的作用。
此时输出结果如下所示:若想修改后的main方法能够在两个线程之间同步运行,需要将testSynchronizedMethod方法声明为静态方法,这样两个线程的监视器是同一个对象(类对象),能够同步执行。修改后的代码如下所示:
输出结果如下:同步块的情况与同步方法类似,只是同步块将同步控制的粒度缩小,这样能够更好的发挥多线程并行执行的效率。
使用this对象控制同一对象实例之间的同步:输出结果:使用class对象控制不同实例之间的同步:
输出结果:
首先来看同步方法的例子:
- public class SynchronizedTest1 extends Thread
- {
- private synchronized void testSynchronizedMethod()
- {
- for (int i = 0; i < 10; i++)
- {
- System.out.println(Thread.currentThread().getName()
- + " testSynchronizedMethod:" + i);
- try
- {
- Thread.sleep(100);
- }
- catch (InterruptedException e)
- {
- e.printStackTrace();
- }
- }
- }
- @Override
- public void run()
- {
- testSynchronizedMethod();
- }
- public static void main(String[] args)
- {
- SynchronizedTest1 t = new SynchronizedTest1();
- t.start();
- t.testSynchronizedMethod();
- }
- }
- main testSynchronizedMethod:0
- main testSynchronizedMethod:1
- main testSynchronizedMethod:2
- main testSynchronizedMethod:3
- main testSynchronizedMethod:4
- main testSynchronizedMethod:5
- main testSynchronizedMethod:6
- main testSynchronizedMethod:7
- main testSynchronizedMethod:8
- main testSynchronizedMethod:9
- Thread-0 testSynchronizedMethod:0
- Thread-0 testSynchronizedMethod:1
- Thread-0 testSynchronizedMethod:2
- Thread-0 testSynchronizedMethod:3
- Thread-0 testSynchronizedMethod:4
- Thread-0 testSynchronizedMethod:5
- Thread-0 testSynchronizedMethod:6
- Thread-0 testSynchronizedMethod:7
- Thread-0 testSynchronizedMethod:8
- Thread-0 testSynchronizedMethod:9
如果此时将main方法修改为如下所示,则两个线程并不能同步执行,因为此时两个线程的同步监视器不是同一个对象,不能起到同步的作用。
- public static void main(String[] args)
- {
- Thread t = new SynchronizedTest1();
- t.start();
- Thread t1 = new SynchronizedTest1();
- t1.start();
- }
此时输出结果如下所示:
- Thread-0 testSynchronizedMethod:0
- Thread-1 testSynchronizedMethod:0
- Thread-0 testSynchronizedMethod:1
- Thread-1 testSynchronizedMethod:1
- Thread-0 testSynchronizedMethod:2
- Thread-1 testSynchronizedMethod:2
- Thread-0 testSynchronizedMethod:3
- Thread-1 testSynchronizedMethod:3
- Thread-0 testSynchronizedMethod:4
- Thread-1 testSynchronizedMethod:4
- Thread-0 testSynchronizedMethod:5
- Thread-1 testSynchronizedMethod:5
- Thread-0 testSynchronizedMethod:6
- Thread-1 testSynchronizedMethod:6
- Thread-0 testSynchronizedMethod:7
- Thread-1 testSynchronizedMethod:7
- Thread-0 testSynchronizedMethod:8
- Thread-1 testSynchronizedMethod:8
- Thread-0 testSynchronizedMethod:9
- Thread-1 testSynchronizedMethod:9
- public class SynchronizedTest1 extends Thread
- {
- private static synchronized void testSynchronizedMethod()
- {
- for (int i = 0; i < 10; i++)
- {
- System.out.println(Thread.currentThread().getName()
- + " testSynchronizedMethod:" + i);
- try
- {
- Thread.sleep(100);
- }
- catch (InterruptedException e)
- {
- e.printStackTrace();
- }
- }
- }
- @Override
- public void run()
- {
- testSynchronizedMethod();
- }
- public static void main(String[] args)
- {
- Thread t = new SynchronizedTest1();
- t.start();
- Thread t1 = new SynchronizedTest1();
- t1.start();
- }
- }
- Thread-0 testSynchronizedMethod:0
- Thread-0 testSynchronizedMethod:1
- Thread-0 testSynchronizedMethod:2
- Thread-0 testSynchronizedMethod:3
- Thread-0 testSynchronizedMethod:4
- Thread-0 testSynchronizedMethod:5
- Thread-0 testSynchronizedMethod:6
- Thread-0 testSynchronizedMethod:7
- Thread-0 testSynchronizedMethod:8
- Thread-0 testSynchronizedMethod:9
- Thread-1 testSynchronizedMethod:0
- Thread-1 testSynchronizedMethod:1
- Thread-1 testSynchronizedMethod:2
- Thread-1 testSynchronizedMethod:3
- Thread-1 testSynchronizedMethod:4
- Thread-1 testSynchronizedMethod:5
- Thread-1 testSynchronizedMethod:6
- Thread-1 testSynchronizedMethod:7
- Thread-1 testSynchronizedMethod:8
- Thread-1 testSynchronizedMethod:9
使用this对象控制同一对象实例之间的同步:
- public class SynchronizedTest2 extends Thread
- {
- private void testSynchronizedBlock()
- {
- synchronized (this)
- {
- for (int i = 0; i < 10; i++)
- {
- System.out.println(Thread.currentThread().getName()
- + " testSynchronizedBlock:" + i);
- try
- {
- Thread.sleep(100);
- }
- catch (InterruptedException e)
- {
- e.printStackTrace();
- }
- }
- }
- }
- @Override
- public void run()
- {
- testSynchronizedBlock();
- }
- public static void main(String[] args)
- {
- SynchronizedTest2 t = new SynchronizedTest2();
- t.start();
- t.testSynchronizedBlock();
- }
- }
- main testSynchronizedBlock:0
- main testSynchronizedBlock:1
- main testSynchronizedBlock:2
- main testSynchronizedBlock:3
- main testSynchronizedBlock:4
- main testSynchronizedBlock:5
- main testSynchronizedBlock:6
- main testSynchronizedBlock:7
- main testSynchronizedBlock:8
- main testSynchronizedBlock:9
- Thread-0 testSynchronizedBlock:0
- Thread-0 testSynchronizedBlock:1
- Thread-0 testSynchronizedBlock:2
- Thread-0 testSynchronizedBlock:3
- Thread-0 testSynchronizedBlock:4
- Thread-0 testSynchronizedBlock:5
- Thread-0 testSynchronizedBlock:6
- Thread-0 testSynchronizedBlock:7
- Thread-0 testSynchronizedBlock:8
- Thread-0 testSynchronizedBlock:9
- public class SynchronizedTest2 extends Thread
- {
- private void testSynchronizedBlock()
- {
- synchronized (SynchronizedTest2.class)
- {
- for (int i = 0; i < 10; i++)
- {
- System.out.println(Thread.currentThread().getName()
- + " testSynchronizedBlock:" + i);
- try
- {
- Thread.sleep(100);
- }
- catch (InterruptedException e)
- {
- e.printStackTrace();
- }
- }
- }
- }
- @Override
- public void run()
- {
- testSynchronizedBlock();
- }
- public static void main(String[] args)
- {
- Thread t = new SynchronizedTest2();
- t.start();
- Thread t2 = new SynchronizedTest2();
- t2.start();
- }
- }
输出结果:
- Thread-0 testSynchronizedBlock:0
- Thread-0 testSynchronizedBlock:1
- Thread-0 testSynchronizedBlock:2
- Thread-0 testSynchronizedBlock:3
- Thread-0 testSynchronizedBlock:4
- Thread-0 testSynchronizedBlock:5
- Thread-0 testSynchronizedBlock:6
- Thread-0 testSynchronizedBlock:7
- Thread-0 testSynchronizedBlock:8
- Thread-0 testSynchronizedBlock:9
- Thread-1 testSynchronizedBlock:0
- Thread-1 testSynchronizedBlock:1
- Thread-1 testSynchronizedBlock:2
- Thread-1 testSynchronizedBlock:3
- Thread-1 testSynchronizedBlock:4
- Thread-1 testSynchronizedBlock:5
- Thread-1 testSynchronizedBlock:6
- Thread-1 testSynchronizedBlock:7
- Thread-1 testSynchronizedBlock:8
- Thread-1 testSynchronizedBlock:9
使用synchronized关键字进行同步控制时,一定要把握好对象监视器,只有获得监视器的进程可以运行,其它都需要等待获取监视器。任何一个非null的对象都可以作为对象监视器,当synchronized作用在方法上时,锁住的便是对象实例(this);当作用在静态方法时锁住的便是对象对应的Class实例。
总结:
synchronized是通过软件(JVM)实现的,简单易用,即使在JDK5之后有了Lock,仍然被广泛地使用。
synchronized实际上是非公平的,新来的线程有可能立即获得监视器,而在等待区中等候已久的线程可能再次等待,不过这种抢占的方式可以预防饥饿。
synchronized只有锁只与一个条件(是否获取锁)相关联,不灵活,后来Condition与Lock的结合解决了这个问题。
多线程竞争一个锁时,其余未得到锁的线程只能不停的尝试获得锁,而不能中断。高并发的情况下会导致性能下降。ReentrantLock的lockInterruptibly()方法可以优先考虑响应中断。 一个线程等待时间过长,它可以中断自己,然后ReentrantLock响应这个中断,不再让这个线程继续等待。有了这个机制,使用ReentrantLock时就不会像synchronized那样产生死锁了。
转自 http://blog.csdn.net/yongmi/article/details/8569886
- Java同步之synchronized
- Java同步之synchronized
- Java同步之synchronized
- java线程同步之synchronized
- Java同步机制 之 synchronized
- java线程之同步synchronized
- java多线程之synchronized(线程同步)
- Java多线程同步总结之synchronized
- JAVA同步之 synchronized关键字详解
- 【JAVA】多线程之synchronized 同步数据 方法
- Java并发同步之synchronized与volatile
- Java多线程-3 线程同步之synchronized
- Java并发编程之同步关键字synchronized
- java并发编程-线程同步之synchronized
- 多线程之同步Synchronized
- java---synchronized同步机制
- Java同步机制--synchronized
- Java同步: synchronized用法
- 反思那十年
- java防止SQL注入的几个途径
- FlyWeight模式
- Rose RealTime C++ Analyzer
- mssqlserver 2008 r2 附加数据库对于服务器失败 处理数据库日志文件时出错
- Java同步之synchronized
- Setting up the C++ Analyzer for MSVC++ 6.0
- web.xml配置Session超时时间注意的单位问题
- 利用 GCC 的 __attribute__ 属性的section选项 来控制 数据区的基地址
- [gpu pro2]PracticalAndRealisticFacialWrinklesAnimation
- .Net中的AutoScrollPosition问题 (panel 滚动条的位置设定)
- 程序员学习能力提升三要素
- Simple Example using the C++ Analyzer with Rose RealTime
- cocs2d-x的安装与配置