Java中的多线程(二)之多线程同步
2014-03-16 09:36
369 查看
多线程同步synchronized
synchronized是Java多线程中比较重要的关键字之一,它可以修饰一个方法或者一段代码块,用以保证每一次最多只有一个线程去访问,是Java实现多线程同步最基本的方式之一
eg:
Thread-0-->0
Thread-1-->1
Thread-1-->2
Thread-0-->3
Thread-1-->4
Thread-0-->5
Thread-0-->6
Thread-1-->6
Thread-1-->8
Thread-0-->7
Thread-0-->9
Thread-1-->10
Thread-1-->11
Thread-0-->12
Thread-1-->13
Thread-0-->13
Thread-1-->15
Thread-0-->14
Thread-1-->16
Thread-0-->16
我们发现,有些数字会出现重复,这个与我们预期的结果出现了偏差,那么把synchronized加上以后会怎么样呢?
Thread-0-->0
Thread-1-->1
Thread-0-->2
Thread-1-->3
Thread-0-->4
Thread-1-->5
Thread-0-->6
Thread-1-->7
Thread-0-->8
Thread-1-->9
Thread-0-->10
Thread-1-->11
Thread-1-->12
Thread-0-->13
Thread-1-->14
Thread-0-->15
Thread-1-->16
Thread-0-->17
Thread-1-->18
Thread-0-->19
这个结果应该是比较满意的,那么synchronized到底做了啥呢?其实,在Java中每一个对象都有一个与之关联的监视器对象,它允许线程对监视器进行加锁和解锁,所以synchronized方法就是对某一个对象进行了加锁,这个对象就是该类的Class对象。
而synchronized如果只是修饰了一小段代码块,那么它加锁的对象需要手动的添加。
eg:
eg:
synchronized是Java多线程中比较重要的关键字之一,它可以修饰一个方法或者一段代码块,用以保证每一次最多只有一个线程去访问,是Java实现多线程同步最基本的方式之一
eg:
public class TestThread { private int value; public static void main(String[] args) { final TestThread tt = new TestThread(); Thread t1 = new Thread(){ @Override public void run() { for(int i=0;i<10;i++){ tt.inc(this.getName()); } } }; t1.start(); Thread t2 = new Thread(){ @Override public void run() { for(int i=0;i<10;i++){ tt.inc(this.getName()); } } }; t2.start(); } public void inc(String threadName) { try { Thread.sleep(300); } catch (InterruptedException e) { } System.out.println(threadName + "-->" + value++); } }上述例子开辟了两个线程去访问同一个对象的inc方法,由于没有使用synchronized来进行同步,看一下输出结果是什么
Thread-0-->0
Thread-1-->1
Thread-1-->2
Thread-0-->3
Thread-1-->4
Thread-0-->5
Thread-0-->6
Thread-1-->6
Thread-1-->8
Thread-0-->7
Thread-0-->9
Thread-1-->10
Thread-1-->11
Thread-0-->12
Thread-1-->13
Thread-0-->13
Thread-1-->15
Thread-0-->14
Thread-1-->16
Thread-0-->16
我们发现,有些数字会出现重复,这个与我们预期的结果出现了偏差,那么把synchronized加上以后会怎么样呢?
public synchronized void inc(String threadName) { try { Thread.sleep(300); } catch (InterruptedException e) { } System.out.println(threadName + "-->" + value++); }结果如下:
Thread-0-->0
Thread-1-->1
Thread-0-->2
Thread-1-->3
Thread-0-->4
Thread-1-->5
Thread-0-->6
Thread-1-->7
Thread-0-->8
Thread-1-->9
Thread-0-->10
Thread-1-->11
Thread-1-->12
Thread-0-->13
Thread-1-->14
Thread-0-->15
Thread-1-->16
Thread-0-->17
Thread-1-->18
Thread-0-->19
这个结果应该是比较满意的,那么synchronized到底做了啥呢?其实,在Java中每一个对象都有一个与之关联的监视器对象,它允许线程对监视器进行加锁和解锁,所以synchronized方法就是对某一个对象进行了加锁,这个对象就是该类的Class对象。
而synchronized如果只是修饰了一小段代码块,那么它加锁的对象需要手动的添加。
eg:
Object o = new Object(); synchronized (o) { //doSomething }这个其实就是锁住了对象o,它能保证的就是任何其它没有拿到监视器对象上的锁的线程都无法访问此段代码。需要注意的是,这种使用方式经常会出现问题,原因在于一个类的Class对象只有一份,所以它的锁也是唯一的,但是手动关联加锁对象经常会出现这个锁不是唯一的情况,比如Object o是在一个方法中定义的,那么任何线程访问这个方法时都会创建一份新的Object,这个时候每个线程需要的锁都是独立的,加锁也就失去了意义。
eg:
public void inc(String threadName) { Object o = new Object(); synchronized (o) { try { Thread.sleep(300); } catch (InterruptedException e) { } System.out.println(threadName + "-->" + value++); } }这段代码演示了synchronized失效的一种情景,每次访问都会产生一个新的o对象,synchronized(o)加锁失去了意义。同理,下段代码与synchronized方法效果相同:
public void inc(String threadName) { synchronized (TestThread.class) { try { Thread.sleep(300); } catch (InterruptedException e) { } System.out.println(threadName + "-->" + value++); } }OK,我们知道在计算机中通常不只有主存,可能还会有缓存、寄存器等其它存储结构。第一节刚开始的时候就说了Java的多线程并发是通过共享内存实现的,而实际情况可能是,线程1要获取一个变量i的值,它会先去缓存中读取,如果缓存中存在,就不会再去主存中读取了,而每个线程都有一份缓存,所以如果缓存更新不及时的话,就会造成多个线程获取的值存在偏差的情况,因此线程获得锁时实际上是将缓存中的内容设置成了无效状态,直接从主存中读取,同样的,当失去锁时,它会将缓存直接写到主存中,从而实现”同步“。
相关文章推荐
- Java 多线程:volatile 多线程同步关键字
- java多线程—Java 多线程同步的五种方法
- Java中级----多线程同步基本思想,java多线程设计wait、notify、notifyall、synchronized的使用机制(转)
- [java多线程]多线程同步(一)——synchronized
- Java中关于同步,异步,多线程,多线程同步,并发,并行的一些总结
- java多线程详解(4)-多线程同步技术与lock
- java破解ip屏蔽+多线程同步拨号-【多线程数据采集之五】
- [java多线程]多线程同步(二)——wait, notify, notifyAll, join以及sleep
- Java 多线程:ThreadLocal 多线程同步关键字
- 【Java多线程编程】典型的多线程同步例程
- Java 多线程:Condition 多线程同步关键字
- Java 多线程:Condition 多线程同步关键字
- Java 多线程同步问题的探究(四、协作,互斥下的协作——Java多线程协作(wait、notify、notifyAll))
- Java【多线程知识总结(7)】多线程同步问题-关于synchronized代码块和synchronized方法的应用
- java多线程-多线程的安全问题-多线程同步代码块-锁Synchronized
- 黑马程序员——java第十一、十二天:多线程(创建线程1-2、多线程同步代码、实现Runnable接口、安全死锁)
- java多线程-多线程同步代码块-银行存款实例-锁synchronized
- Java【多线程知识总结(7)】多线程同步问题-关于synchronized代码块和synchronized方法的应用
- Java 多线程:synchronized 多线程同步关键字
- java破解ip屏蔽+多线程同步拨号-【多线程数据采集之五】