GVKun编程网logo

java 线程安全问题(java线程安全问题如何查)

1

对于java线程安全问题感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍java线程安全问题如何查,并为您提供关于02、线程安全问题、6.ArrayList线程安全问题、Android开发——线

对于java 线程安全问题感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍java线程安全问题如何查,并为您提供关于02、线程安全问题、6.ArrayList 线程安全问题、Android开发——线程安全问题、asp.net – HMACSHA1.ComputeHash()线程安全问题的有用信息。

本文目录一览:

java 线程安全问题(java线程安全问题如何查)

java 线程安全问题(java线程安全问题如何查)

java线程安全的处理我知道的现在就2种
lock、synchronized
我想线程安全封装在我框架的底层。但是在开发中我始终有个疑问

比如我有这样一个对象


public class User {
	private int id;
	private String name;
	private int money;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getMoney() {
		return money;
	}
	public void setMoney(int money) {
		this.money = money;
	}
}



我现在需要查询 UserDao 类



public class UserDao {
	public User getById(int id){
		...
	}
	
	public User getByType(int type){
		...
	}
}



我查询出来会执行修改,而为了保证我数据的安全 synchronized此时感觉就没多大用了(我查询出来返回的是原数据的一个clone对象)


为何synchronized不起作用呢?下面代码解释

public class A_Thread implements Runnable{
	public void run() {
		//此时查询出来的数据是原数据的一个clone 原数据再怎么变这个对象也不会受影响
		User user = UserDao.getById(1);
		Thread.sleep(1000);
		user.setMoney(user.getMoney()+10);
		user.update();
	}
}

public class B_Thread implements Runnable{
	public void run() {
		//此时查询出来的数据是原数据的一个clone 原数据再怎么变这个对象也不会受影响
		User user = UserDao.getById(1);
		Thread.sleep(1000);
		user.setMoney(user.getMoney()+10);
		user.update();
	}
}

public class Test{
	public static void main(String[] agrs){
		ExecutorService exe = Executors.newFixedThreadPool(8);
		exe.execute(new A_Thread());
		exe.execute(new B_Thread());
	}
}


public static void main(String[] agrs){
		User user = UserDao.getById(1);
		int money = user.getMoney();
		money = ???
	}

结果这个user的 值根本确定不了 无论在那加 synchronized

public synchronized int getMoney() {
		return money;
	}
	public synchronized void setMoney(int money) {
		this.money = money;
	}

到这大概有人会说把User保留一分在内存中,查询始终,修改始终都是操作的内存中这个User对象!

但会有以下几个问题

1.数据会出出现完整性问题(多线程并发的时候 你一个逻辑线程需要set 10属性,但才3个,另外一个逻辑线程要取这个对象,那个瞬间他取过去的数据实际上就只改了3个属性)
2.如果我set了 但是update失败!但是内存中的数据任然有部分已经受到了影响

好了!synchronized不能很好的解决我的问题,那么我就来用Lock。Lock必须显示的加锁和放锁

我要防止上面的问题,在比如getById()的时候就有了2中加锁方式,加读锁和写锁。我需要修改的查询就在调用getById中加上写锁,只读不修改的时候就加读锁。而现在问题又来了
并且我是加在User的实例对象上的,加载Dao也可以但性能会底很多!
1.我加了写锁之后必须等我逻辑线程处理完后 简单的说就是要 update之后才能放锁!

2.如果逻辑线程在取得写锁后逻辑出现异常了!导致没有换锁!

解决这个我的处理试了一下几种

1.加了个最大持有该锁的时间,当另外一个线程要获得该锁的时候检查时间,如果超过时间,中断持有改锁的线程(不大友好)

2.定时检查,但并发高的时候会有很多定时器

3.改造getById(int id)方法,getById(int id,List<Lock> locks) 在查询中传一个List进去,把该次操作的的Lock反馈出来,在逻辑处理完后全部释放!

List<Lock> locks = new ArrayList();
		try {
			//业务逻辑
			getById(1,locks);
		} catch (Exception e) {
			
		}finally{
			//locks 全部释放掉
		}



我想问下你们一般线程安全是怎么处理的呢!还有除了我说的3种,还有什么好的处理方式呢!






02、线程安全问题

02、线程安全问题

 

CAS存在的问题:

1、循环+CAS,自旋的实现让所有线程处于高频运行,争抢cpu执行时间的状态。如果操作长时间不成功,会带来很大的cpu资源消耗。

2、仅针对单个变量操作,不能用于多个变量来实现原子性操作。

3、ABA问题。(可以加上版本号机制予以解决)

6.ArrayList 线程安全问题

6.ArrayList 线程安全问题

OSC 请你来轰趴啦!1028 苏州源创会,一起寻宝 AI 时代

转:

6.ArrayList 线程安全问题

题出问题

我们知道 ArrayList 是线程不安全,请编写一个不安全的案例并给出解决方案?

单线程环境

单线程环境的 ArrayList 是不会有问题的

public class ArrayListNotSafeDemo {
    public static void main(String[] args) {

        List
  
  
   
    list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");

        for(String element : list) {
            System.out.println(element);
        }
    }
}
  
  

多线程环境

为什么多线程环境下 ArrayList 是线程不安全的?因为在进行写操作(add 方法)的时候,方法上为了保证并发性,没有添加 synchronized 修饰。

当我们同时启动 30 个线程去操作 List 的时候

public class Test {
    public static void main(String[] args) {

        List
  
  
   
    list = new ArrayList<>();

        for (long i = 0; i < 30; i++) {
            new Thread(() -> {

                list.add("hello");
                list.add("world");
                list.add("java");
                System.out.println(list);

            }).start();
        }

    }
}
  
  

我们运行发现报了 java.util.ConcurrentModificationException(并发修改的异常)

解决方案

方案一:Vector

采用 Vector 实现线程安全,Vector 在方法上加了锁,即 synchronized

这样就每次只能够一个线程进行操作,所以不会出现线程不安全的问题,但是因为加锁了,导致并发性下降。

方案二:Collections.synchronized ()

List
  
  
   
    list = Collections.synchronizedList(new ArrayList<>());
  
  

采用 Collections 集合工具类,在 ArrayList 外面包装一层 同步 机制

方案三:采用 JUC 里面的方法

CopyOnWriteArrayList:写时复制,主要是一种读写分离的思想。

  • 就是写的时候,把 ArrayList 扩容一个出来,然后把值填写上去,在通知其他的线程,ArrayList 的引用指向扩容后的。
  • CopyOnWriteArrayList
        
        
         
          list = new CopyOnWriteArrayList<>();
        
        
查看 add 方法源码

  1. 首先需要加锁

    final ReentrantLock lock = this.lock;
    lock.lock();
  2. 然后在末尾扩容一个单位

    Object[] elements = getArray();        
    int len = elements.length;
    Object[] newElements = Arrays.copyOf(elements, len + 1);//扩容一个单位,复制到新数组
  3. 然后在把扩容后的空间,填写上需要 add 的内容

    newElements[len] = e;
  4. 最后把内容 set 到 Array 中

应用场景:一般用于黑 / 白名单,这样的地方,标准的读多写少场景

HashSet 线程不安全

CopyOnWriteArraySet(底层还是用的 CopyOnWriteArrayList)

HashMap 线程不安全

  1. 使用 Collections.synchronizedMap(new HashMap<>())
  2. 使用 ConcurrentHashMap

    Map
        
        
         
          map = new ConcurrentHashMap<>();
        
        

转:

6.ArrayList 线程安全问题


--Posted from Rpc

Android开发——线程安全问题

Android开发——线程安全问题

死锁

产生的原因:

  • 多个操作者争夺多个资源(操作者>资源数>=2)
  • 拿到资源不放手
  • 争夺资源的顺序不对

危害:

  • 线程不工作了,但是整个程序还是活着的
  • 没有任何的异常信息可以供我们检查
  • 一旦程序发生了发生了死锁,是没有任何的办法恢复的,只能重启程序,对正式已发布程序来说,这是个很严重的问题。

解决方式:

  • 调整拿锁的顺序,采用尝试拿锁机制(tryLock)。
  • 内部通过顺序比较,确定拿锁的顺序。

 

活锁

 

两个线程在尝试拿锁的机制中,发生多个线程之间互相谦让,不断发生同一个线程总是拿到同一把锁,在尝试拿另一把锁时因为拿不到,而将本来已经持有的锁释放的过程。

 

解决办法:每个线程休眠随机数,错开拿锁的时间。

 

线程饥饿

 

低优先级的线程,总是拿不到执行时间

asp.net – HMACSHA1.ComputeHash()线程安全问题

asp.net – HMACSHA1.ComputeHash()线程安全问题

我问自己,在asp.net页面的代码隐藏中使用包含HMACSHA1实例的静态(共享)变量是否有危险.问题是当在同一个asp.net页面上处理多个同时请求时,所有asp.net worker-process’线程将使用相同的HMACSHA1实例.
all(HMACSHA1)instance-和ComputeHash() – 由ComputeHash()使用/修改的方法变量将被所有线程共享(=可以修改)?这个假设是正确的吗?
因此,ComputeHash的返回值不能保证是正确的?!?!
因此我不允许在所有的asp.net-threads上使用静态/共享HMACSHA1实例.

我只是想知道你对这个问题的看法.

解决这个问题的唯一方法就是在ComputeHash()方法中使用关键路径等.但那是“我们无法接触到的”..

问候,
短剑的一种

解决方法

散列算法是确定性的,它们必须每次都为给定的输入返回相同的散列.

只要您每次使用相同的密钥,就不需要将它们设置为静态.但是,如果您使用无参数构造函数构造HMACSHA1实例,则它会生成随机密钥.您应该从keyvalue属性中获取随机值并将其与散列一起存储.

使用静态实例肯定是危险的.如果Thread1设置要计算的值,然后Thread2在Thread1调用ComputerHash()之前设置该值,则Thread1将获取Thread2值的散列值.如果任一线程正在设置密钥,则会发生相同的情况.

关于java 线程安全问题java线程安全问题如何查的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于02、线程安全问题、6.ArrayList 线程安全问题、Android开发——线程安全问题、asp.net – HMACSHA1.ComputeHash()线程安全问题的相关知识,请在本站寻找。

本文标签: