实现同步组件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. centos7 firewall指定IP与端口、端段访问(常用)

    https://blog.csdn.net/yipianfuyunsm/article/details/99998332 https://www.cnblogs.com/co10rway/p/8268 ...

  2. docker 第六篇 dockerfile

    复习下镜像生成途径 Dockerfile 基于容器制作 什么是dockerfile: 用来构建镜像的源码,在配置文件中调用命令,这些命令是用来生成docker镜像的. dockerfile的语法格式: ...

  3. 微信小程序跳到指定页面不生效

    wx.redirectTo({ url: './index', }) wx.navigateTo({ url: './index', }) 用了这两种都没生效,点击没跳转,也没报错 后来想了下是不是因 ...

  4. Mysql与java对应的类型表

    1. 概述 在使用Java JDBC时,你是否有过这样的疑问:MySQL里的数据类型到底该选择哪种Java类型与之对应?本篇将为你揭开这个答案. 2. 类型映射  java.sql.Types定义了常 ...

  5. 使用nodejs实现OData的batch操作在Marketing Cloud里读取contact信息

    我们先来看看Marketing Cloud系统里的contact信息: 一共1218374条数据. 我们用如下的nodejs代码通过OData来获取这些数据: var request = requir ...

  6. Java基础加强-日志

    /*日志*/ 从功能上来说,日志API本身所需求的功能非常简单,只需要能够记录一段文本即可 API的使用者在需要记录时,根据当前的上下文信息构造出相应的文本信息,调用API完成记录.一般来说,日志AP ...

  7. 多进程编程——理论讲解与 multiprocessing 模块

    多进程编程 import os pid = os .fork() 功能 :创建新的进程 参数: 无 返回值 :失败返回一个负数 成功:在原有进程中返回新的进程的PID号 在新进程中返回为0* 子进程会 ...

  8. 03_Redis_String命令

    一:Redis命令---String命令:Redis 字符串数据类型的相关命令用于管理 redis 字符串值 字符串类型是Redis中最为基础.常用的数据存储类型,字符串在Redis中是二进制安全的, ...

  9. 表单重置时 <input type=“hidden”> 隐藏域不可被重置

    可封装全局样式 .hide{ display:none; } 用 <input type="text" class="hide"/> 替代

  10. memory management Vulkan

    https://www.youtube.com/watch?v=rXSdDE7NWmA vulkan 1. DEVICE_LOCAL_BIT | HOST_VISIBLE_BIT | HOST_COH ...