关于JAVA编程思想中synchronized和ReentrantLock

在学习JAVA编程思想并发一章时,关于synchronized和ReentrantLock的例子运行
结果与书中不一致。代码如下:

 package thinking.in.java.chapter21;

class Pair {
    private int x,y;
    public Pair(int x, int y) {
        this.x = x;
        this.y = y;
    }
    public Pair() {
        this(0,0);
    }
    public int getX(){
        return x;
    }
    public int getY(){
        return y;
    }
    public void incrementX(){x++;}
    public void incrementY(){y++;}
    @Override
    public String toString() {
        return "x=" + x + ", y=" + y;
    }
    public class PairValuesNotEqualException extends RuntimeException {
        public PairValuesNotEqualException() {
            super("Pair values not equal: " + Pair.this);
        }
    }
    public void checkstate(){
        if(x != y)
            throw new PairValuesNotEqualException();
    }
}

package thinking.in.java.chapter21;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public abstract class PairManager {
    AtomicInteger checkCounter = new AtomicInteger(0);
    protected Pair p = new Pair();
    private List<Pair> storage = 
            Collections.synchronizedList(new ArrayList<Pair>());
    public synchronized Pair getPair(){
        return new Pair(p.getX(),p.getY());
    }

    protected void store(Pair p){
        storage.add(p);
        try{
            TimeUnit.MILLISECONDS.sleep(50);
        }catch(InterruptedException e){}
    }
    public abstract void increment();

}

package thinking.in.java.chapter21;

public class PairChecker implements Runnable {

    private PairManager pm;
    public PairChecker(PairManager pm) {
        this.pm = pm;
    }

    @Override
    public void run() {
        while(true){
            pm.checkCounter.incrementAndGet();
            pm.getPair().checkstate();
        }

    }

}

package thinking.in.java.chapter21;

public class PairManager1 extends PairManager {

    @Override
    public synchronized void increment() {
        p.incrementX();
        p.incrementY();
        store(getPair());
    }
}

package thinking.in.java.chapter21;

public class PairManager2 extends PairManager {

    @Override
    public void increment() {
        Pair temp;
        synchronized (this) {
            p.incrementX();
            p.incrementY();
            temp = getPair();
        }
        store(temp);

    }

}

package thinking.in.java.chapter21;

public class PairManipulator implements Runnable {
    private PairManager pm;
    public PairManipulator(PairManager pm) {
        this.pm = pm;
    }
    @Override
    public void run() {
        while(true)
            pm.increment();
    }
    @Override
    public String toString() {
        return "Pair: " + pm.getPair() +
                " checkerCounter = " + pm.checkCounter.get();
    }

}

package thinking.in.java.chapter21;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class CriticalSection {
    static void testApproaches(PairManager pman1,
            PairManager pman2){
        ExecutorService exec = Executors.newCachedThreadPool();
        PairManipulator 
            pm1 = new PairManipulator(pman1),
            pm2 = new PairManipulator(pman2);
        PairChecker
            pchecker1 = new PairChecker(pman1),
            pchecker2 = new PairChecker(pman2);
        exec.execute(pm1);
        exec.execute(pm2);
        exec.execute(pchecker1);
        exec.execute(pchecker2);
        try{
            TimeUnit.MILLISECONDS.sleep(1000);
        }catch(InterruptedException e){
            System.err.println("Sleep interrupted");
        }
        System.out.println("pm1: " + pm1 + "\npm2: " + pm2);
        System.exit(0);
    }
    public static void main(String[] args) {
        PairManager
            pman1 = new PairManager1(),
            pman2 = new PairManager2();
        testApproaches(pman1, pman2);
    }
}

package thinking.in.java.chapter21;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ExplicitPairManager1 extends PairManager {
    private Lock lock = new ReentrantLock();
    @Override
    public void increment() {
        lock.lock();
        try{
            p.incrementX();
            p.incrementY();
            store(getPair());
        }finally{
            lock.unlock();
        }

    }

}

package thinking.in.java.chapter21;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ExplicitPairManager2 extends PairManager {

    private Lock lock = new ReentrantLock();
    @Override
    public void increment() {
        lock.lock();
        Pair temp;
        try{
            p.incrementX();
            p.incrementY();
            temp = getPair();
        }finally{
            lock.unlock();
        }
        store(temp);
    }

}

package thinking.in.java.chapter21;

public class ExolicitCritialSection {
    public static void main(String[] args) {
        PairManager
            pman1 = new ExplicitPairManager1(),
            pman2 = new ExplicitPairManager2();
        CriticalSection.testApproaches(pman2, pman1);
    }
}

按照书中所说,ExolicitCritialSection和CriticalSection都不应该抛出PairValuesNotEqualException异常,可是ExolicitCritialSection中的两个线程都抛出了该异常,
个人分析在进行increment的时候,虽然是同步操作,可是在进行PairChecker时checkstate方法并未同步,他可以访问Pair对象中的X和Y值,所以按照书中的列子感觉都应该抛出PairValuesNotEqualException异常才对,为什么只有ExolicitCritialSection会抛出那????

2个回答

求并发高手解答啊!!

没人能解答吗?还是代码太多了啊

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
ReentrantLock与synchronized
NULL 博文链接:https://uule.iteye.com/blog/1488356
ReentrantLock与synchronized区别
java语言 并发编程 ReentrantLock与synchronized区别 详解
ReentrantLock 与 synchronized 简介
java lock synchronized
synchronized 与 ReentrantLock 同步代码块简单实现
synchronized 与 ReentrantLock 简单实现
【锁机制】synchronized和ReentrantLock、锁优化
java中的锁的种类很多。目前对这部分知识点只是停留在了解的基础上,就目前知识进行梳理,并长期补充。 java中锁常用的为synchronized 和java.util.concurrent.Lock下的锁。 这是一篇对各种分类锁的介绍:https://blog.csdn.net/u013256816/article/details/51204385  下面对java中实现的锁进行个人分析 ...
ReentrantLock比synchronized 强大在哪儿?
官方说明:一个可重入的互斥锁定 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁定相同的一些基本行为和语义,但功能更强大。rnrn强大在哪儿?求高人解释。
Synchronized与ReentrantLock比较以及ReentrantLock使用场景以及注意事项
锁的实现 Synchronized是依赖于JVM实现的,而ReenTrantLock是JDK实现。可重入性,两者都是同一个线程每进入一次,锁的计数器自增1,所以要等到锁的计数器下降为0时才能释放锁。 功能方面 便利性:Synchronized的使用比较方便简洁,并且由编译器去保证锁的加锁和释放。ReenTrantLock需要手工声明来加锁和释放锁,为了避免忘记手工释放锁造成死锁,所以最好...
Java并发——Synchronized和ReentrantLock的联系与区别
0 前言 本文通过使用synchronized以及Lock分别完成“生产消费场景”,再引出两种锁机制的关系和区别,以及一些关于锁的知识点。 本文原创,转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52401134 1. synchronized, wait, notify结合实现生产消费场景 1.1 生产者类 ...
ReenTrantLock可重入锁(和synchronized的区别)总结
ReenTrantLock可重入锁(和synchronized的区别)总结 可重入性: 从名字上理解,ReenTrantLock的字面意思就是再进入的锁,其实synchronized关键字所使用的锁也是可重入的,两者关于这个的区别不大。两者都是同一个线程没进入一次,锁的计数器都自增1,所以要等到锁的计数器下降为0时才能释放锁。   锁的实现: Synchronized是依赖于JVM实现的
ReentrantLock synchronized的区别以及简单示范
ReentrantLock简称可重入的互斥锁,当一个线程多次获取它所占有的锁资源时,是可以成功的,每当成功获取一次的时候,其保持计数将会+1,并且在其执行完毕释放锁的时候,保持计数随之清零;至于互斥的概念,就是当一个线程持有该锁时,其他需要获取该锁的线程将一直等待直至该锁被释放;这是多线程中实现同步的一种方式,它实现了synchronized的基本功能,同时也拓展了一些新的方法。   sy...
Synchronized与ReentrantLock区别总结(简单粗暴,一目了然)
这篇文章是关于这两个同步锁的简单总结比较,关于底层源码实现原理没有过多涉及,后面会有关于这两个同步锁的底层原理篇幅去介绍。 相似点: 这两种同步方式有很多相似之处,它们都是加锁方式同步,而且都是阻塞式的同步,也就是说当如果一个线程获得了对象锁,进入了同步块,其他访问该同步块的线程都必须阻塞在同步块外面等待,而进行线程阻塞和唤醒的代价是比较高的(操作系统需要在用户态与内核态之间来回切换,代价很高...
线程同步的方法:Synchronized、Lock、ReentrantLock分析
Synchronized: Synchronized修饰的代码块或者方法被某个线程获取到之后,其他线程就会被阻塞。当被修饰的方法执行完后则自动释放锁 Lock: Lock是一个接口,lock提供比Synchronized更广泛的锁操作,他们允许更灵活的结构化可能具有完全不同的属性 ,并且可以支持多个相关联的对象Condition 。 下面列出Lock的常用方法: void lock(): 获得...
Synchronized与重入锁ReenTrantLock的区别 个人总结
Synchronized与重入锁ReenTrantLock的区别 ReenTrantLock比Synchronized多了三个功能1.      等待可中断在持有锁的等待线程尝试集不释放锁的时候,等待线程可以选择放弃等待2.      公平锁按照申请锁的顺序来一次获取锁称为公平锁,但synchronized是非公平锁,ReentrantLock可以通过构造函数实现公平锁3.      绑定多个Co...
【Java】【多线程】Synchronized 和 ReentrantLock的联系与区别
转载:https://blog.csdn.net/u011202334/article/details/73188404 1、synchronized的局限性    synchronized是java内置的关键字,它提供了一种独占的加锁方式。synchronized的获取和释放锁由JVM实现,用户不需要显示的释放锁,非常方便。然而synchronized也有一定的局限性,例如:当线程尝试获取锁的时...
Synchronized和ReentrantLock包装线程不安全的类_demo
线程之synchronized和ReentrantLock
ReentrantLock与synchronized在与数据库交互时的问题
ReentrantLock与synchronized在操作数据库时的不同,在多线程的环境中
java的两种同步方式, Synchronized与ReentrantLock的区别
 java在编写多线程程序时,为了保证线程安全,需要对数据同步,经常用到两种同步方式就是Synchronized和重入锁ReentrantLock。 相似点:        这两种同步方式有很多相似之处,它们都是加锁方式同步,而且都是阻塞式的同步,也就是说当如果一个线程获得了对象锁,进入了同步块,其他访问该同步块的线程都必须阻塞在同步块外面等待,而进行线程阻塞和唤醒的代价是比较高的(操作系统...
synchronized和ReentrantLock异常退出时的锁处理
在JDK5.0之前,在协调对共享对象的访问时可以使用的机制只有synchronized和volatile. JDK5.0新增了ReentrantLock,作为一种可选的高级功能.ReentrantLock必须要在finally中unlock(), 否则,如果在被加锁的代码中抛出了异常,那么这个锁将会永远无法释放. synchronized就没有这样的问题, 遇到异常退出时,会释放掉已经获得的锁.
synchronized和ReentrantLock实现消费者生产者问题
并发执行和并行执行的区别:并行执行是指两个或多个事件在同一时刻发生,而并发执行是指两个或多个事情在同一时间间隔内发生。并发执行在宏观层面上看,事情之间是同时发生的。比如说在2秒的时间内发生的两件事情,在历史的角度上可以看作是“同时发生”的。 在Java中,多个线程对临界区资源操作时,需要保持程序的可再现性,或者说内存可见性。不管哪个线程操作了临界资源,操作的结果都应该对下一个操作该资源的线程可见
多线程-ReentrantLock(可重入锁)与synchronized比较
可重入锁新特征: 可中断响应; 锁限时操作; 公平锁; 非公平锁; 结合Condition使用; 继承关系: Lock定义了锁的接口规范。 ReentrantLock实现了Lock接口。 AbstractQueuedSynchronizer中以队列的形式实现线程之间的同步。 ReentrantLock的方法都依赖于AbstractQueuedSynchronizer的实现。 sync是在Re...
《Java并发编程实战》读书笔记——synchronized和ReentrantLock
1、synchronized确保线程互斥访问同步代码,synchronized和volatile都保证了内存可见性,解决了重排序(为了充分利用多核、多级缓存)。    内存可见性:每个CPU都有自己的缓存区,其他CPU上的线程无法看到该CPU对变量的修改。    synchronized和ReentrantLock一样,也是可重入的。为什么需要可重入,看如下代码,如果synchronized不是可...
线程同步的方法:Synchronized、lock、reentrantLock分析
线程同步的方法:Synchronized、lock、reentrantLock分析
Java 多线程(四)——线程同步(synchronized、ReentrantLock)
在多线程编程里面,一些敏感数据不允许被多个线程同时访问,此时就使用同步访问技术,保证数据在任何时刻,最多有一个线程访问,以保证数据的完整性。   synchronized关键字和Lock对象。
基础篇:同步机制之synchronized与ReentrantLock(五)
我们继续来探讨同步机制的话题; 上一篇文章说到了使用ReentrantLock的lock()来获取锁,但有时候我们可能有这样的需求,我们先尝试着去获取锁,但等了几秒实在拿不到锁就放弃获取锁而转做其它的事情,这个需求是很常见的, 所幸的是,ReentrantLock提供了tryLock方法来帮助我们达到这样的目的; //演示锁的tryLock方法 public static void test
基础篇:同步机制之synchronized与ReentrantLock(四)
什么是同步呢?同步就是指串行访问,在单线程的情况下,不用考虑同步的问题,因为不存在并行访问,而在多线程情况下,假设我们有个取款的方法, 它可能是这样的: public static void 取款( int 款数 ){ int 余额 = get余额(); if( 余额>款数 ){ //代码1处 吐钱(); //代码2处 更新数据库余额(); }else{ System.
synchronized与ReentrantLock的介绍、使用、适合场景及比较
JDK 5.0为开发人员开发高性能的并发应用程序提供了一些很有效的新选择,目前存在两种锁机制:synchronized和Lock,Lock接口及其 实现类是JDK5增加的内容,ReentrantLock是Lock的实现。在实际的工作中,大家对synchronized和ReentrantLock都使用的比较多, 今天对这 两种锁机制进行了总结并分享给各位朋友们,希望对大家有所帮助。
java的两种同步方式, Synchronized与ReentrantLock的区别
java在编写多线程程序时,为了保证线程安全,需要同步,经常用到两种同步方式就是Synchronized和重入锁ReentrantLock。 相似点: 这两种同步方式有很多相似之处,它们都是加锁方式同步,而且都是阻塞式的同步,也就是说当如果一个线程获得了对象锁,进入了同步块,其他访问该同步块的线程都必须阻塞在同步块外面等待,而进行线程阻塞和唤醒的代价是比较高的(操作系统在用户态与内核态之间来回
浅谈synchronized关键字和ReenTrantLock可重入锁
ReenTrantLock单单字面意思就可以理解是可重入的锁,其实synchronized关键字所使用的锁也是可重入的,这方面区别不大。两者都是同一个线程每进入一次,锁的计数器都自增1,所以要等到锁的计数器下降为0时才能释放锁。 看一个例子: 本例中由于m1锁定this,只有m1执行完毕后,m2才能执行。这里是复习synchronized最原始的语义 package com.example...
各种同步方法性能比较(synchronized,ReentrantLock,Atomic)
5.0的多线程任务包对于同步的性能方面有了很大的改进,在原有synchronized关键字的基础上,又增加了ReentrantLock,以及各种Atomic类。了解其性能的优劣程度,有助与我们在特定的情形下做出正确的选择。 总体的结论先摆出来: synchronized: 在资源竞争不是很激烈的情况下,偶尔会有同步的情形下,synchronized是很合适的。原因在于,编译程序...
公平锁,非公平锁,乐观锁,悲观锁、ReenTrantLock、synchronized
参考: 面试必备之乐观锁与悲观锁 公平锁,非公平锁,乐观锁,悲观锁 ReenTrantLock可重入锁(和synchronized的区别)总结 悲观锁: 总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。 传统的关系型数据库里边就用到了很多这种...
谁的锁,锁的谁--关于synchronized、ReentrantLock的正确解锁姿势
线程安全是并发编程中的一个重大关注点,所谓线程安全就是要保证在多个线程间读写共享数据保证正确性,如果不能保证,那就不是线程安全的了。 synchronized、ReentrantLock都是用来实现线程间同步,访问同步的代码需要先获得锁,保证每次都只能有一个线程进入同步块,代码执行完毕后释放锁,从而保证了线程间的安全。 所以在实现线程安全中需要考虑的核心问题就是“谁的锁,锁的谁”,只要记住这条规则,就大体上能够达
Java中的可重入锁ReentrantLock以及synchronized实现多人抢票
在前面的抢票中出现了多个人抢到了同一张票,还有负数。可以发现多线程出现了问题。这是由于同一进程的多个线程共享一块存储空间,在带来方便的时候,也带来了访问冲突问题,为了保证数据在方法中被访问时的正确性,在访问时加入了锁机制synchronized当一个线程获得对象的排它锁,独占资源,其他线程必须等待,使用后释放锁。判断一个多线程是否有问题的标准: 是否是多线程环境 是否存在共享数据 是否存在多条语...
Java中的ReentrantLock和synchronized两种锁定机制的对比
http://blog.csdn.net/fw0124/article/details/6672522       别人理解如下: 如果我们把每个线程理解成 一个个门,门都需要上锁, 在没有ReentrantLock之前,我们上锁,可能统一用sycnchronized(钥匙),大家都在竞争锁钥匙,钥匙只有一把,谁先拥有谁就先开门进去,门打不开的就一直卡死等待,浪费时间,还不能干其他...
Java中的ReentrantLock和synchronized两种锁定机制的对比 -- 转
  阅读本文,使我从对比的角度重新审视了两种锁的机制。 分享一下下O(∩_∩)O   原文出处:  http://www.ibm.com/developerworks/cn/java/j-jtp10264/index.html
Synchronized,ReentrantLock的实现原理及异同比较 、Java中其他锁的理解
1)Synchronized 同步锁 作用域:不同加锁方式对应不同作用域 1) 对象锁 当一个对象访问Synchronized方法时,锁类型为对象锁。 此时该对象不能同时访问类中其他Synchronized方法。若一个对象中有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,则其它线程不能同时访问这个对象中任何一个synchronized方法。 此外,不...
关于ReentrantLock使用的疑问?
直接上代码:nn```nimport java.util.concurrent.locks.ReentrantLock;nnpublic class MulThreadTest n public static int a = 0;n n ReentrantLock lock = new ReentrantLock(true);n public void addInt()n lock.lock();n a++;n System.out.println(Thread.currentThread().getName()+"___________"+a +"_ " + lock.getHoldCount());n lock.unlock();n n public static void main(String[] args) throws InterruptedException n for(int i=0;i<3;i++)n new Thread(new Runnable() n @Overriden public void run() n MulThreadTest test = new MulThreadTest();n for(int j=0;j<100;j++)n test.addInt();n n ,"thread"+i).start();n n n n```n运行结果总会丢数字,难道是使用方法有问题?帮忙解答一下~nn
关于Synchronized?
[color=#FF0000]synchronized (parent.getTreeLock())[/color]rn谁能帮我详细解释一下这段代码啊?谢谢rn我只知道synchronized加在方法名前可以声明该方法为共享资源,线程利用的,别的就不知道了
关于synchronized
想使用线程同步,以保证在同一个时刻只有一个线程能够执行某部分代码。rn我使用的是同步代码块。rn线程部分代码如下:rn[code=java]class MyThread implements Runnablernrn @Overridern public void run() rn // TODO Auto-generated method stubrn while(true)rn synchronized (this)rn if(a>0)rn System.out.println(a+" "+Thread.currentThread().toString());rn a--;rn rn else break;rn rn rn rn [/code]rnrn创建和启动线程部分代码如下:rn[code=java]MyThread tt=new MyThread();rn Thread t1=new Thread(tt);rn t1.setName("thread 1");rn Thread t2=new Thread(tt);rn t2.setName("thread 2");rn Thread t3=new Thread(tt);rn t3.setName("thread 3");rn t1.start();rn t2.start();rn t3.start();[/code]rn我的程序达到了预定效果。rn但是我很郁闷,原来学的时候synchronized (this)这个地方填上任何对象都可以,但是今天调试的时候却发现只能填this ,填一个普通的对象无法达到线程同步的效果。([color=#FF0000]即输出结果里面a值有相同的!!!这可是线程同步正要解决的问题啊!!![/color])
关于synchronized!
各位谁知道我这程序怎么一直都一个线程工作啊?去掉synchronized后多线程。怎么回事啊?rnrn[code=Java]class TestSynchronizedrnrn public static void main(String[] args)rn rn Ticket t = new Ticket();rn new Thread(t).start();rn new Thread(t).start();rn new Thread(t).start();rn rnrnrnclass Ticket implements Runnablernrn int ticket = 100;rn String str = new String("");rn public void run()rn rn while(true)rn rn /*synchronized(str)rn rn if(ticket > 0)rn rn tryrn Thread.sleep(100);rn catch(Exception e)rn System.out.println(Thread.currentThread().getName() + " :sales a ticket:" + ticket--);rn rn */rn sale();rn rn rn rn public synchronized void sale()rn rn if(ticket > 0)rn rn tryThread.sleep(100);rn catch(Exception e)rn System.out.println(Thread.currentThread().getName() + " :sales a ticket:" + ticket--);rn rn rn[/code]
关于java中的synchronized的用法
今天要分享的内容是synchronized这个地方也是,说起来知道同步的用法,但是并不是多么的清楚,和上面的那篇mysql的子查询一样,看到代码中很多这样写的。 就顺便研究总结一下: 修饰对象有几种(能出现在什么地方) 修饰一个类,其作用的范围是synchronized后面括号括起来的部分, 作用的对象是这个类的所有对象。 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法, 作用的对
相关热词 c# stream 复制 android c# c#监测窗口句柄 c# md5 引用 c# 判断tabtip 自己写个浏览器程序c# c# 字符串变成整数数组 c#语言编程写出一个方法 c# 转盘抽奖 c#选中treeview