实现同步组件twinsLock:可以允许两个线程同时获取到锁,多出的其它线程将被阻塞。

以下是自定义的同步组件类,一般我们将自定义同步器Sync定义为同步组件TwinsLock的静态内部类。

实现同步器需要继承AbstractQueuedSynchronizer并覆盖相应的方法。

package com.lock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

public class TwinsLock implements Lock {
private final Sync sync=new Sync(2);
//自定义一个同步器,作为自定义同步组件的静态内部类
private static final class Sync extends AbstractQueuedSynchronizer{
Sync(int count){
if(count<=0){
throw new IllegalArgumentException("count must large than zero");
}
setState(count);//设置同步状态

}
/**
* 尝试以共享方式获取同步状态
* return 大于0时表示获取成功
*/
@Override
public int tryAcquireShared(int reduceCount){
for(;;){
int current=getState();
int newCount=current-reduceCount;
if(newCount<0||compareAndSetState(current, newCount)){
return newCount;
}
}
}
/**
* 同步器中的释放同步状态的方法
*/
@Override
public boolean tryReleaseShared(int returnCount){
for(;;){
int current=getState();
int newCount=current+returnCount;
if(compareAndSetState(current, newCount)){
return true;
}
}
}
}

@Override
public void lock() {
sync.acquireShared(1);
}

@Override
public void unlock() {
sync.releaseShared(1);
}

@Override
public void lockInterruptibly() throws InterruptedException {
// TODO Auto-generated method stub

}

@Override
public Condition newCondition() {
// TODO Auto-generated method stub
return null;
}

@Override
public boolean tryLock() {
// TODO Auto-generated method stub
return false;
}

@Override
public boolean tryLock(long arg0, TimeUnit arg1)
throws InterruptedException {
// TODO Auto-generated method stub
return false;
}

}

下面是测试类,注意将线程实现类放在方法内和放在方法外时,对线程共享变量的区别

1,

package com.lock;

import java.util.concurrent.locks.Lock;

public class TwinsLockTest {

public static void main(String[] str) throws InterruptedException {
//将内部类放在方法内部,共享变量必须定义为final
final Lock twinsLock=new TwinsLock();
class Worker extends Thread{
public void run(){
while(true){
twinsLock.lock();

try{
Thread.sleep(10000);
System.out.println(Thread.currentThread().getName());
Thread.sleep(10000);
}catch(Exception e){
e.printStackTrace();
}finally{
twinsLock.unlock();
}
}
}

}
for(int i=0;i<10;i++){
Worker worker=new Worker();
worker.setDaemon(true);
worker.start();
}
for(int i=0;i<10;i++){
Thread.sleep(500000);
System.out.println("....................");
}

}

}

2,

package com.lock;

import java.util.concurrent.locks.Lock;

public class TwinsLockTest2 {
//将外部类放在方法外面,共享变量必须定义为static才能保证同步。不然的话每个线程对象都拥有一个共享变量的拷贝
static Lock twinsLock=new TwinsLock();
public static void main(String[] str) throws InterruptedException {

for(int i=0;i<10;i++){
Worker worker=new TwinsLockTest2().new Worker();
worker.setDaemon(true);
worker.start();
}
for(int i=0;i<10;i++){
Thread.sleep(500000);
System.out.println("....................");
}

}

class Worker extends Thread{
public void run(){
while(true){
twinsLock.lock();

try{
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName());
Thread.sleep(2000);
}catch(Exception e){
e.printStackTrace();
}finally{
twinsLock.unlock();
}
}
}

}

}

java实现自定义同步组件的过程的更多相关文章

  1. 学习JUC源码(2)——自定义同步组件

    前言 在之前的博文(学习JUC源码(1)--AQS同步队列(源码分析结合图文理解))中,已经介绍了AQS同步队列的相关原理与概念,这里为了再加深理解ReentranLock等源码,模仿构造同步组件的基 ...

  2. 011-多线程-基础-基于AbstractQueuedSynchronizer自定义同步组件

    一.概述 队列同步器AbstractQueuedSynchronizer,是用来构建锁或者其他同步组件的基础框架. 1.1.自定义独占锁同步组件 设计一个同步工具:该工具在同一时刻,只允许一个线程访问 ...

  3. 基础篇:JAVA原子组件和同步组件

    前言 在使用多线程并发编程的时,经常会遇到对共享变量修改操作.此时我们可以选择ConcurrentHashMap,ConcurrentLinkedQueue来进行安全地存储数据.但如果单单是涉及状态的 ...

  4. 构建锁与同步组件的基石AQS:深入AQS的实现原理与源码分析

    Java并发包(JUC)中提供了很多并发工具,这其中,很多我们耳熟能详的并发工具,譬如ReentrangLock.Semaphore,它们的实现都用到了一个共同的基类--AbstractQueuedS ...

  5. AQS 原理以及 AQS 同步组件总结

    1 AQS 简单介绍 AQS 的全称为(AbstractQueuedSynchronizer),这个类在 java.util.concurrent.locks 包下面. AQS 是一个用来构建锁和同步 ...

  6. Java显式锁学习总结之二:使用AbstractQueuedSynchronizer构建同步组件

    Jdk1.5中包含了并发大神Doug Lea写的并发工具包java.util.concurrent,这个工具包中包含了显示锁和其他的实用同步组件.Doug Lea在构建锁和组件的时候,大多是以队列同步 ...

  7. Java 线程同步组件 CountDownLatch 与 CyclicBarrier 原理分析

    1.简介 在分析完AbstractQueuedSynchronizer(以下简称 AQS)和ReentrantLock的原理后,本文将分析 java.util.concurrent 包下的两个线程同步 ...

  8. Java并发包源码学习系列:同步组件CountDownLatch源码解析

    目录 CountDownLatch概述 使用案例与基本思路 类图与基本结构 void await() boolean await(long timeout, TimeUnit unit) void c ...

  9. java并发编程(7)构建自定义同步工具及条件队列

    构建自定义同步工具 一.通过轮询与休眠的方式实现简单的有界缓存 public void put(V v) throws InterruptedException { while (true) { // ...

随机推荐

  1. 出现 HTTP 错误 500.19 错误代码 0x800700b7

    这个内容出现主要问题是在IIS上,我们一般程序开发 iis中默认的路径只是http://localhost/,相当于环境变量中已定义好了,如果自己创建的项目直接将路径定义到这,就会替换图二中的路径,然 ...

  2. 小知识:修改IDEA的模板

    小知识:修改IDEA的模板 有时候我们会发现,IDEA默认创建的模板并不是我们常用的.与其每次都在创建后进行修改,不如直接对模板进行修改. 给不知道怎么修改的同学指一下路: File->sett ...

  3. Graphics与Canvas

    Graphics: 1. java.awt.Graphics;2.android.graphics Canvas:1.java.awt.Canvas;2.android.graphics.Canvas ...

  4. 07 Redis存储Session

    django-redis-sessions 官方文档:https://pypi.org/project/django-redis-sessions/ dango-redis 官方文档:http://n ...

  5. span元素

    <span>标签属于行内元素(inline),所以无法设置高度和宽度: 如果需要改变其宽高,就需要将其转变为块体元素(block)或行内块体元素(inle-block)

  6. 利用axis调用webservice接口

    一.首先把wsdl文件放入eclipse中某个项目中的src目录下 二.右键弹出webservice,然后点击webservice菜单,选中genernator client ,选择axis生成Jav ...

  7. DevExpress VCL 19.2.3 Skin找不到皮肤

    The location where the DX Designtime Loader is looking for the skin packages has changed again ! For ...

  8. windows下如何打开.sketch的文件

    1 .sketch的文件只能在苹果mac上支持的一种文件格式,现在越来越多的设计师喜欢用.sketch 2 windows下如果想打开.sketch文件,去Microsoft store 找一个Lun ...

  9. linux基础_用户和组的三个文件

    1./etc/passwd文件 用户(user)的配置文件,记录用户的各种信息 每行的含义:用户名:口令:用户标识号:组标识号:注释性描述:主目录:登录shell 2./etc/shadow文件 口令 ...

  10. 00-c#与设计模式目录

    工作5年多了,使用的语言是asp.net(c#),感觉自己遇到了技术瓶颈,以前一直忙着做兼职.接私活.加班,没有时间静下来好好想想自己的发展方向,就着春节期间放假,没事自己躺在老家的火炕上,问自己想要 ...