做钓鱼网站违法吗,网站建设需要编程吗,大学生做网站赚钱,购物网站成品并发是带来有趣挑战的一个方面。 如果处理不当#xff0c;会导致种族状况#xff0c;这会使人们感到困惑#xff0c;因为这些问题有时会突然出现#xff0c;并且有时会完美无缺地发挥作用。 当处理访问公共资源的并发线程时#xff0c;Java语言提供了许多处理竞争条件的方… 并发是带来有趣挑战的一个方面。 如果处理不当会导致种族状况这会使人们感到困惑因为这些问题有时会突然出现并且有时会完美无缺地发挥作用。 当处理访问公共资源的并发线程时Java语言提供了许多处理竞争条件的方法。 一些包括 使用volatile关键字 使用java.util.concurrent和 java.util.concurrent.atomic中可用的类 同步块 使用信号量 当然可能还有很多我可能不知道的事情。 今天我想向大家展示的例子是使用 信号量 。 它是从JDK 1.5引入的使开发人员能够无缝获取和释放锁。 我还将显示的示例是一个假设的场景该场景仅用于描述使用信号量可以实现的效果因此请不要看代码的固有细节:)。 因此在这种情况下存在一个内存缓存中保存了类型为 人。 用户可以使用缓存插入和检索记录。 这里的问题是我们将使用信号量来控制对内存缓存的并发访问。 现在我不想给您带来更多文本让我们开始业务并显示一些代码 import java.util.concurrent.Semaphore;/*** This class will allow thread to acquire and release locks as required* * author dinuka.arseculeratne* */
public class PersonLock {/*** We do not want multiple lock objects lying around so we make ths class* singleton*/private PersonLock() {}/*** Bill Pughs way of lazy initializing the singleton instance* * author dinuka.arseculeratne* */private static class SingletonHolder {public static final PersonLock INSTANCE new PersonLock();}/*** Use this method to get a reference to the singleton instance of* {link PersonLock}* * return the singleton instance*/public static PersonLock getInstance() {return SingletonHolder.INSTANCE;}/*** In this sample, we allow only one thread at at time to update the cache* in order to maintain consistency*/private Semaphore writeLock new Semaphore(1);/*** We allow 10 concurrent threads to access the cache at any given time*/private Semaphore readLock new Semaphore(10);public void getWriteLock() throws InterruptedException {writeLock.acquire();}public void releaseWriteLock() {writeLock.release();}public void getReadLock() throws InterruptedException {readLock.acquire();}public void releaseReadLock() {readLock.release();}
} 此类将处理获取和释放使我们的缓存线程安全所需的锁的过程。 我在这里使用了两个单独的锁进行读写。 其背后的原理是允许用户读取数据尽管在读取时可能已过时。 请注意我已经使用 这里的“十”表示十个线程可以同时获取锁并出于读取目的访问缓存。 接下来您可以在写锁中看到我已经使用了“ 一个” 表示一次只有一个线程可以访问缓存以将项目放入缓存。 这对于保持缓存内的一致性很重要。 也就是说我不希望有多个线程试图将项目插入到地图中这将导致不可预测的行为至少在某些情况下。 使用信号量获取锁的方式主要有两种。 1. Acquisition 是一个阻塞调用它等待直到释放锁或线程被中断为止 2. tryAcquire 是一个非阻塞调用它将立即返回并返回true或false表示是否已获得锁定。 在这里我使用了阻塞获取调用因为我希望线程等待直到锁可用。 当然这取决于您的用例。 您还可以在tryAcquire方法中定义超时期限以使线程不会无限期地等待锁定。 接下来下面的存储类显示了我如何使用锁类在缓存中插入和读取数据。 import java.util.HashMap;
import java.util.Map;/*** A mock storage to hold the person objects in a map* * author dinuka.arseculeratne* */
public class PersonStorage {private MapInteger, Person personCache new HashMapInteger, Person();private int counter 0;/*** This class is made singleton and hence the constructor is made private*/private PersonStorage() {}/*** Bill Pughs way of lazy initializing the singleton instance* * author dinuka.arseculeratne* */private static final class SingletonHolder {public static final PersonStorage INSTANCE new PersonStorage();}/*** Use this method to get a reference to the singleton instance of* {link PersonStorage}* * return the singleton instance*/public static PersonStorage getInstance(){return SingletonHolder.INSTANCE;}/*** Inserts the person into the map. Note that we use defensive copying so* that even if the client changes the object later on, those changes will* not be reflected in the object within the map* * param person* the instance of {link Person} to be inserted* return the key which signifies the location of the person object* throws InterruptedException*/public int putPerson(Person person) throws InterruptedException {Person copyPerson person.copyPerson();personCache.put(counter, copyPerson);return counter;}/*** Here as well we use defensive copying so that the value of the object* reference within the map is not passed in to the calling party.* * param id* the id representing the location of the object within the map* return the instance of the {link Person} represented by the key passed* in* throws InterruptedException*/public Person retrievePerson(int id) throws InterruptedException {PersonLock.getInstance().getReadLock();if (!personCache.containsKey(id)) {throw new RuntimeException(Key is not found);}PersonLock.getInstance().releaseReadLock();return personCache.get(id).copyPerson();}} 显然代码也可以在没有锁的情况下工作但是问题是应用程序将不一致并且每次运行都会提供不同的结果。 这不是您希望应用程序执行的操作因此使用锁可以确保应用程序始终运行。 最后是一个小型测试类以展示其工作方式 并不是在这里我们在调用putPerson方法之前获得了锁并在finally块中释放了该锁以保证释放该锁。 /*** A test class to demonstrate the locking at work* * author dinuka.arseculeratne* */
public class TestLock {public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(new Runnable() {Overridepublic void run() {Person p1 new Person(1L, Test1, XYZ);try {
PersonLock.getInstance().getWriteLock();
PersonStorage.getInstance().putPerson(p1);} catch (InterruptedException e) {// Exception handling need to be donee.printStackTrace();}finally{PersonLock.getInstance().releaseWriteLock();}}});Thread t2 new Thread(new Runnable() {Overridepublic void run() {Person p2 new Person(2L, Test123, ABC);try {
PersonLock.getInstance().getWriteLock();PersonStorage.getInstance().putPerson(p2);} catch (InterruptedException e) {// Exception handling need to be done}finally{PersonLock.getInstance().releaseWriteLock();}}});t1.start();t2.start();System.out.println(PersonStorage.getInstance().retrievePerson(2));}
} 以上是我对使用Sempahores来确保代码线程安全的简短介绍的总结对于任何想使用该代码的人来说都可以从 在这里 。 尝试删除Storage类中的锁并查看其在每次运行中的行为。 您将看到可能发生的比赛情况。 参考 使用信号灯锁定我们的JCG合作伙伴 Dinuka Arseculeratne 的示例来自“ IT之旅”博客。 翻译自: https://www.javacodegeeks.com/2012/10/locking-with-semaphore-example.html