java 多线程方法加锁获取自增变量重复问题 1C

/**

  • 测试多线程并发获取唯一子增长的值
  • @author Administrator
    *
    */
    public class BB {
    private int increment = 0;

    final static Set set = new HashSet();
    final static List list = new ArrayList();
    public synchronized int getauto() {
    return increment++;
    }
    public static void main(String[] args) throws Exception {
    final BB b = new BB();
    Vector workers = new Vector();
    for (int i = 0; i < 2; i++) {
    final Thread t = new Thread(new Runnable() {

            @Override
            public void run() {
                synchronized (this) {
                    for (int j = 0; j < 10000; j++) {
                        int num = b.getauto();
                        System.out.println(String.valueOf(num));
                        set.add(num);
                        list.add(num);
                    }
                }
    
            }
        });
        workers.add(t);
        t.setName("thread-" + i);
        t.start();
    }
    for (Thread t : workers) {
        t.join();
    }
    System.out.println("set  size :" + set.size());
    System.out.println("list  size :" + list.size());
    

    }
    }
    list和set的size不同

1

5个回答

System.out.println("set size :" + set.size());
System.out.println("list size :" + list.size());
这两句可没有在锁区域内,一个线程完毕后,在这两句执行的任意时刻,另一个线程可能已经开始执行,并改写了list

0

for (Thread t : workers) {
t.join();
}
这个是等待线程都执行完毕

0

System.out.println("set size :" + set.size());
System.out.println("list size :" + list.size());
这两句肯定是线程都执行完了,才打印出来的。预期结果set和list的size都是20000

0

hashset、arraylist是线程不安全的,你这样写,有时候会得到正确的长度。同步一下就好。。

0

你的工作线程的run方法中synchronize是用的this,是指当前线程对象,这样的话,每个线程都是有自己的this对象,所有线程run时锁都不一样,怎么能保证对共享变量的同步呢?那必定会出现同时操作set和list共享变量的情况啊
修正代码,使用外界共享对象作为锁,例如用final BB b,或者直接对list和set进行加锁,就能保证run中的代码每次只有一个线程能获取到锁。

 synchronized (b) {
                        for (int j = 0; j < 10000; j++) {
                            int num = b.getauto();
                            System.out.println(String.valueOf(num));
                            set.add(num);
                            list.add(num);
                        }
                    }

这个问题,主要是每个工作线程在run中用的锁不同,你的代码锁在线程对象this上,就相当于根本没有同步处理。

0
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
其他相关推荐
java线程同步中使用自增操作时的注意
在这里讲一个很多新手可能会出错的地方:就是在线程中进行加法操作,这里说的是 在多线程中操作同一份内存中的数据,然后对其进行加法运算。 不要觉得不就是加法嘛,会有什么问题。要是这样我还说个球啊!!不过,讲道理我在大学里学习数据库的理论知识的时候也没记得说加法也会存在线程同步的问题。废话不多说先来看一个简单的例子class MyThread extends Thread{ public void
JAVA多线程-对象及变量的并发访问(一)synchronized详解
一、synchronized同步方法 1.1 方法内的变量为线程安全     非线程安全的问题存在于“实例变量”中,如果是方法内部的私有变量,则不存在“非线程安全”问题,所得结果也就是“线程安全”的了。 1.2 实例变量非线程安全     如果多个线程共同访问1个对象中的实例变量,则有可能出现“非线程安全”问题。 1.3 多个对象多个锁     synchronized关
多线程并发已经加了锁,仍出现数据不准确问题
这边记一次线上出现的bug,场景描述: 服务端提供了获取码的接口,这个接口有2个动作,查询码,然后将查询出的码在表中删除,可是当多个线程并发访问时,第二个线程可以查询出第一个线程已经删除的码,这就有问题了。 排查问题: 1.怀疑是mybatis缓存引起的,把缓存关掉,还是有问题; 2.参考:链接内容 这篇文章可以确定问题是关于事务的。 解决办法: 法1.去掉service里的事务; ...
Java多个线程同时访问操作单例对象,需不需要加锁的问题
1、多个线程处理单例对象的共有属性         如果两个线程同时访问同一个方法的时候,如果这个方法操作了单例对象中共有的属性,则需要加锁。 2、多个线程不是处理单例对象的共有属性(可能调用的是某个方法,该方法没有操作对象中的全局属性)         多个线程如果不是同时处理一个对象的共有属性,则不会出现线程问题,即使是方法中的属性。         如果两个线程同时访问同一个方法的时...
多线程 变量 加锁问题
对于x86来说如果其地址是4字节对齐的,那访问是就原子操作。这也是最常见的情况,注意访问是读或写,不是自增等。 如果你有个这样的结构体,还禁用了对齐的话那就不是了。 struct S { char a; int b; }; http://www.xuebuyuan.com/2214900.html 对于多线程编程,很多人概念不清,写代码的时候要么是处处加锁,影响性能不说,还容易莫名
[java多线程]关于Java和Scala同步机制你不知道的5个真相
实际上,所有的服务器应用在多线程中都需要某种类型的同步机制。框架已经为我们做了大多数的同步的工作,这些框架包括web服务器、数据库连接客户端、消息框架等。我们可以通过Java和Scala提供的多种组件来写出可靠的多线程应用。这些组件包括,对象池、并发集合类、高级锁、执行上下文等。 为了更好的理解这个问题,接下来首先要探究最常用的同步模式:对象锁。这种机制增强了synchroniz
关于多线程加锁问题
偶然间翻到了多线程加锁的帖子,记录一下 多线程间共享变量加不加锁取决于变量类型以及大小,跟CPU单次操作有关。 从:https://blog.csdn.net/youtherzhang/article/details/76093570 大神的测试结果来看(感谢大神的这么详细的测试数据) 结论: 1.对于int,short,char,BOOL等小于等于4字节的简单数据类型,如果无逻辑上的先后...
多线程自增运算的原子性与可见性分析
很多程序的复杂性都是由于并发引起的,如果在并发情况下,如果对象是无状态那可以很好的运行,无论是在单线程还是多线程环境下都没问题,但是很多时候对象的状态是需要上下文维护的,因此在并发情况下就很容易导致不一致性的情况。我们先看下面一个例子:class File { private int num; public void incr() throws InterruptedException
多线程自增问题
i++ 考虑变量i++的操作,实际上可以分解为以下3步: (1)从内存单元读入寄存器; (2)在寄存器中对变量做增量操作; (3)把新的值写回内存单元。 如果两个线程试图几乎在同一时间对同一变量做增量操作而不进行同步的话,结果可能就不一致了,在上述代码中,我们传进线程函数的是变量的地址,那么变量i自增后,可能还没有写回内存单元,就被另一个线程读取了,那为什么不是只创建了一个线程了,而是确
JAVA中如何保证线程安全以及主键自增有序
一、常见场景 多个线程针对一个i进行主键自增。多线程下如果不做安全策略,将会导致各个现成获取的i值重复,导致脏数据 常见策略 1、增加syschroize进行线程同步 2、使用lock、unlock处理 3、使用reetrantent 锁进行锁定 缺点:容易造成性能低下,或者编写代码容易造成死锁 二、新方案 jdk新提供的功能,atomicInteger
Java 多线程加锁的方式总结及对比
参考博文:http://www.cnblogs.com/handsomeye/p/5999362.html 一.Java多线程可以通过: 1. synchronized关键字 2. Java.util.concurrent包中的lock接口和ReentrantLock实现类 这两种方式实现加锁。 二.synchronized关键字加锁的缺陷: 如果一个代码块被s
MongoDB自增序列实现 - Java多线程同步 synchronized 用法
转 : 简书 - MongoDB自增序列实现 - Java多线程同步 synchronized 用法 在使用MongoDB的时候 (基于spring-mongo) ,我想在插入对象时获取有序自增的主键 ,但是MongoDB的默认规则是生成一串无序 (大致有序) 的字串 .而Spring Data提供的主键生成方法也是随机的 String/BigInteger. 因为分布式情况下 ,有序I
Java 多线程锁,根据值进行加锁
最近在一个需求中 遇到 say(int a) ,有N个线程对这个函数进行访问,不需要对有所线程进行同步,但是当a值相同的线程要进行同步。 之前所看到synchronized 都是 根据对象锁进行同步。 现在要做的是根据值进行同步。 synchronized( object) object 相同时会进行同步, 实现 synchronized(value) 普通的值相同也...
线程安全实现自增
业务设计走过的坑之存储过程 1、存储过程的使用将导致整个项目无法更好的实现负载均衡配置 2、存储过程在使用的时候会受到许多的局限性,最大的问题只适合于但数据库实例,当系统要执行某些庞大开销的时候,那么存储过程的出现将会给你的系统带来致命打击。
java 多线程加锁-锁住了什么?
Java 锁机制
C++中多线程的加锁机制
问题来源于某面试题: 编写一个单例模式的类。 #include #include #include using namespace std; class singleStance{ private : singleStance(); public : static singleStance* onlystance; static singleStance* getStance(
多线程共享全局变量和加锁机制
  import threading VALUE = 0 def add_value(): #引用全局变量,并保证全局变量不被清零,使用global global VALUE for x in range(1000): VALUE += 1 print('value:%d' % VALUE) def main(): for x in ...
多线程高并发下的主键自增策略
AtomicInteger类的理解与使用 首先看两段代码,一段是Integer的,一段是AtomicInteger的,为以下: public class Sample1 { private static Integer count = 0; synchronized public static void increment() { count++;
Java多线程(8)——锁实现和重入锁
锁实现基础 Lock接口 Lock接口是JDK1.5新加入的,它可以实现比synchronized更丰富灵活的功能,同时也更易用。 在Lock接口基础上建立了重入锁,读写锁等一系列并发控制工具,因此Lock接口以及和它紧密相关的同步器是需要理解的概念。 Lock接口定义如下方法: void lock() 获取锁 void unlock() 释放锁 void lockInterrup
Java多线程--多个对象多个锁
上一篇博客中介绍了多个线程同时访问一个对象,产生一个对象锁,属于同步访问,现在介绍下如果是访问多个对象,会怎么执行那? Demo: HasSelfPrivateNum类: public class HasSelfPrivateNum { private int num=0; synchronized public void addI(String username){ ...
多线程访问变量是否要加锁
是否要加锁? 加锁的代价有多大? 现在有个变量 static int g_delRecordFlag = 0;多个线程同时访问,加了互斥锁,感觉资源消耗的有点多。 这个变量即使多个线程访问冲突,也没有什么大的问题,很纠结是否加锁。 询问同事,arm访问int是原子型的,可以不加锁。 网上查询了下, 1.int变量读写是否是原子操作,是平台相关的,可以看内核相应平台的atomic.h中对
线程安全的AtomicLong使用
看一个计数的类: public class Counter { private static long counter = 0; public static long addOne(){ return ++counter; } } 初看感觉没啥问题,但这个类在多线程的环境下就会有问题了。 假如开多个线程都来使用这个计数类,它会表现的“不稳定” public static
线程安全之如何实现多线程下的自增安全
package com.ilucky.test.jdk.util.concurrent;import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger;/** * 线程安全: 当多个线程访问某个类时, 这个类始终都能表现出正确的行为, 那么就称这个类是线程安全的。 * @au
mysql高并发下主键冲突
事情是这样的,博主刚刚写完一个小项目,由于使用的量比较大,所以做了一下压测,在插入数据的时候报出了如下错误 :[http-bio-****-exec-67] DEBUG c.j.m.a.d.A.insertAppUser!selectKey - ==&amp;gt; Parameters: org.springframework.dao.DuplicateKeyException: ### Error u...
多线程读一个全局变量要不要加锁?还是说只是当修改全局变量的时候才要加锁?...
如果所有线程都只读取该变量的话不必加锁,因为仅读取不存在破坏数据的风险,如果有线程写该变量的话不管读取还是写入都要加锁的。
用java生成高并发下的唯一的案件编号:
预备知识: 1、AtomicInteger 这个类真的非常实用,更重要的是 它确实非常简单: 附上自己的代码,可以自己试试: AtomicInteger,一个提供原子操作的Integer的类。在Java语言中,++i和i++操作并不是线程安全的,在使用的时候,不可避免的会用到synchronized关键字。而AtomicInteger则通过一种线程安全的加减操作接口。
Java多线程 之 访问共享资源synchronized、lock(七)
上一篇博文引出了资源竞争,并使用例子展示了资源竞争产生的结果(错误)。这篇博文给出解决方法。1. synchronized解决线程冲突的方案基本上都是:序列化访问共享资源。即当多个线程对共享资源同时访问时,对共享资源加锁访问。在Java中提供了synchronized关键字。 在java中,所有对象都自动含有单一的锁。也就是说,当一个任务调用某个对象上被synchronized标识的f()方法时,
C#多线程Lock锁定的使用例子(多线程线程同步)
这个例子是一个模拟多个人在多台提款机上同时提取一个账户的款的情况。 在存取的过程中 可能 A线程取了100   而B线程那边还看见账户上没少掉那100快,所以导致数据不统一,赋值出现问题。 下面代码则可以测试出加上Lock锁定 与 不加的区别。   先上两个图。 第一个(加了Lock的程序):   加了的 数据每一条都是完整无错的,因为他们执行Lo
java-多线程同时操作同一个对象之解决方法:读写锁ReadWriteLock的使用
说明一下,这边文章写得比较简单,只涉及到ReadWriteLock的使用,具体源码实现原理并不涉及。 1、使用场景:            首先我这边是实际开发中使用到了,开发的环境情况为:有一个数据中心(暂且当做一个Map集合),有两个子线程A、B,其中A线程每5秒钟从其他地方获取到新来的数据然后和数据中心里面的数据进行一个融合,然后B线程进行隔5分钟从数据中心取出Map集合并解析其中的数据...
多线程,高并发的情况下操作redis当中的数据,如何加锁?
多个线程同时去操作Redis当中的数据,假如不加锁的情况下,会出现数据重复的问题。假如需要每次都只有一条线程去操作Redis当中的数据,需要给操作加上锁。     但是去网上一搜,网上给Redis加锁的机制都是利用Redis的setnx自身的方法去加锁,但是这样加锁首先麻烦,得手动防止死锁等问题,速度还不快。     下面是我自己测试通过的如何给redis加锁的代码,仅供自己参考和有需要的人参
多线程访问同一变量是否需要加锁
对于多线程访问同一变量是否需要加锁的问题,先前大家都讨论过。今天用代码验证了一下之前的猜想:32位CPU与内存的最小交换数据为4字节/次,这也是结构体要对齐4字节的原因。在物理上,CPU对于同一4字节的内存单元,不可能写2个字节的同时,又读了3字节。 测试环境为: XEON 2CPU*2 Windows7 采用50,50,50线程交叉读写,试验代码如下: C/C+
原子类与多线程中变量的累加问题
java并发包中的原子类的知识和多线程中对变量累加的同步操作
C#多线程怎么锁定全局变量
主线程和子线程全局变量共享数据 public static Dictionary dictionary = new Dictionary(); public static object locker = new object();//添加一个对象作为锁 public static void AddRecord()//线程1循环调用此函数 { lock (
i++和++i在多线程中的表现,volatile和加锁
只有加锁够得出争取的结果: 控制台输出: i++的结果: 1000012113 ++i的结果: 1000003505 volatile i++的结果: 1018584689 volatile ++i的结果: 995483979 加锁 i++的结果: 2000000000 加锁  ++i的结果: 2000000000 测试代码如下: / public c
Python线程,以及多线程带来的数据错乱和死锁的解决方法
摘至本人有道云笔记《Python线程》 1.python多线程的创建 在Python中,同样可以实现多线程,有两个标准模块thread和threading,不过我们主要使用更高级的threading模块 threading模块提供的类:      Thread, Lock, Rlock, Condition, [Bounded]Semaphore, Event, Timer, local。...
多线程并发获取订单号
[b]使用倒计数器(信号量)重现高并发场景:[/b] [code=&quot;java&quot;] package com.baozun.trade; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.CountDownLatch; import java.util.concur...
《现代操作系统》阅读笔记——竞争与加锁
竞争发生在当多线程同时访问同一个内存,各个线程执行的顺序有交叉时。 一般来说,局部变量和参数由于对每个线程是独立的,不会发生竞争。竞争通常发生在全局变量,堆变量等上。 解决竞争最简单的方法就是进入临界区(开始读写公共内存)时屏蔽掉中断,但是这种方法对于多CPU无效,因为该内存可能会被别的CPU中的程序访问。现在更好的方法是屏蔽那片内存的访问(以前是通过锁住总线解决的)。但是还是会有问题,因为这样...
多线程中使用静态方法存在线程安全的问题
类的成员分两类,静态成员(static member)和实例成员(instance menber),静态成员属于类,实例成员则属于对象,即类的实例。    我们知道,静态字段和静态方法的调用都是通过类来调用的,静态方法不会对特定的实例操作,只能调用调用类中的其他属性和静态方法,不能调用类中的非静态属性和非静态方法。实例方法可以对特定的实例操作,既能访问静态属性和静态方法,也能访问实例属性和实例方
多线程 加锁的三种方式
加锁的第一种方式: public class RootBeanDefinition{ final Object constructorArgumentLock = new Object(); final Object postProcessingLock = new Object(); public void registerExternallyManagedCon
C# ASP.NET B/S模式下,采用lock语法 实现多用户并发产生不重复递增单号的一种解决方法技术参考
<br />有时候也好奇,若是老外发个技术文章,会不会到处是有人骂街的?进行人身攻击的?中国人喜欢打击别人,不知道老外是不是也是这个性格?好奇的问一下大家。<br /> <br />往往我们在开发程序、调试程序时,无法模拟多用户同时操作的实际环境下的运行情况。<br />为了模拟多用户并发操作,我们先写个多线程的例子来充分模拟多用户并发的情况代码    class SequenceTest<br />    {<br />        /// <summary><br />        /// 定义委托
文章热词 设计制作学习 机器学习教程 Objective-C培训 交互设计视频教程 颜色模型
相关热词 mysql关联查询两次本表 native底部 react extjs glyph 图标 java多线程学习指南 java 多线程学习笔记