java并发之(4):Semaphore信号量、CounDownLatch计数锁存器和CyclicBarrier循环栅栏
简介
java.util.concurrent包是Java 5的一个重大改进,java.util.concurrent包提供了多种线程间同步和通信的机制,比如Executors, Queues, Timing, Synchronizers和Concurrent Collections等。与synchronized关键字和Object.notify()等方法相比,这些类和方法的抽象层次都较高。Effective Java中提到,其中比较重要的同步和通信机制有Executor框架、Concurrent Collections和Synchronizers三种。
其中Synchronizers包含了五种: Semaphore信号量,CounDownLatch倒计时锁存器,CyclicBarrier循环栅栏,Phaser和Exchanger。 JCIP中提到,Exchanger可以看做一种特殊的Barrier。Effective Java 提到用的比较多的主要是Semaphore信号量和CounDownLatch倒计时锁存器。本文主要讲解我认为比较重要的Semaphore信号量、CounDownLatch计数锁存器和CyclibBarrier。每一种都按照它们的概念、jdk实现、所提供的方法和使用(traveler或者jdk, or sample code)来进行介绍。
1 Semaphore
semaphore,信号量,是众多synchronizer中的一个。在操作系统中就存在互斥量和信号量这样的概念。 semaphore跟锁机制存在一定的相似性,semaphore也是一种锁机制,所不同的是,reentrantLock是只允许一个线程获得锁,而信号量持有多个许可(permits),允许多个线程获得许可并执行。从这个意义上看,重入锁是许可只有1的信号量。它们所提供的方法也非常接近。
1.1 实现
跟ReentrantLock一样,Semaphore也是以AQS为基础来实现的。
1.1.1 构造函数:
非公平版本:
1 public Semaphore(int permits) {
2 sync = new NonfairSync(permits);
3 }
可以选择是否公平的版本:
1 public Semaphore(int permits, boolean fair) {
2 sync = fair ? new FairSync(permits) : new NonfairSync(permits);
3 }
1.1.2 其他方法
跟ReentrantLock不同的是,每种acquire方法都分为有参数的和不带参数的两个版本:
acquire() :
1 public void acquire() throws InterruptedException {
2 sync.acquireSharedInterruptibly(1);
3 }
acquire(int permits)
1 public void acquire(int permits) throws InterruptedException {
2 if (permits < 0) throw new IllegalArgumentException();
3 sync.acquireSharedInterruptibly(permits);
4 }
与此类似的还有:
acquireUninterruptibly()&acquireUninterruptibly(int)
tryAcquire()& tryAcquire(int)
tryAcquire(long,TimeUnit)& tryAcquire(int, long,TimeUnit)
release()& release(int)
aaarticlea/png;base64,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" alt="" />
1.2 使用示例:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore; public class TIJ_semaphore {
public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
final Semaphore semp = new Semaphore(5); // 5 permits for (int index = 0; index < 20; index++) {
final int NO = index;
Runnable run = new Runnable() {
public void run() {
try {
// if 1 permit avaliable, thread will get a permits and go; if no permit avaliable, thread will block until 1 avaliable
semp.acquire();
System.out.println("Accessing: " + NO);
Thread.sleep((long) (10000);
semp.release();
} catch (InterruptedException e) {
}
}
};
exec.execute(run);
}
exec.shutdown();
}
程序输出结果为:
1 Accessing: 0
2 Accessing: 2
3 Accessing: 3
4 Accessing: 4
5 Accessing: 1
6 (等待10s)
7 Accessing: 5
8 Accessing: 6
9 Accessing: 14
10 Accessing: 8
11 Accessing: 7
12 (等待10s)
13 Accessing: 10
14 Accessing: 9
15 Accessing: 11
16 Accessing: 15
17 Accessing: 12
18 (等待10s)
19 Accessing: 13
20 Accessing: 16
21 Accessing: 17
22 Accessing: 19
23 Accessing: 18
2 CountDownLatch
2.1 实现
内部使用AQS实现
2.2 方法
await()
等待,无超时,可以被中断
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
boolean await(long,timeUnit):
如果等待超时,则返回false; 如果时间为0或者为负,则立刻返回。
public boolean await(long timeout, TimeUnit unit)
throws InterruptedException {
return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
}
countDown():
把Latch的计数减1,如果计数到达0,则释放所有正在等待的线程。
public void countDown() {
sync.releaseShared(1);
}
2.3 使用:
绝大多数synchronizer在jdk中没有使用,原因很简单:这些synchronizer是抽象层次较高的,所以一般只有应用程序才会直接使用。
而在nts生产环境中,只有一处admin.rest.api.RestRequestSender使用了CountDownLatch:
public Map<String, List<JSONObject>> doDelete(final String reqUri, final HttpHeaders _headers)
throws RestAPIException
{
setMethod(Method.DELETE);
setUriTemplate(reqUri);
headers = _headers;
return processBroadcast();
}
doDelete调用了processBraodcast:
private Map<String, List<JSONObject>> processBroadcast() throws RestAPIException
{
...
final Map<String, SaaSServerContext> dServers = RestRequestSender.deployedServers;
if (!dServers.isEmpty())
{
final CountDownLatch doneSignal = new CountDownLatch(dServers.size());
...
for (final String key : dServers.keySet())
{
...
executor.submit(new RRSRunnable(doneSignal, context, results, key, totalRecordsCounter));
} try
{
if (!doneSignal.await(Configuration.NTS_MDM_API_BROADCAST_TIMEOUT.getInt(), TimeUnit.MINUTES)) // if timeout will retrun false
{
XLog.warning("MDM api broadcast timed out after " + Configuration.NTS_MDM_API_BROADCAST_TIMEOUT.getInt()
+ " minutes. Timeout is set via notes.ini key "
+ Configuration.NTS_MDM_API_BROADCAST_TIMEOUT.getNotesIniName());
}
}
catch (final InterruptedException ie)
{
throw new RestAPIException("Interrupted", ie);
} } return results; // if doneSingnal.await has been intrerrupted, will this line still execute?
}
RRSRunnable代码如下:
class RRSRunnable implements Runnable
{
private final CountDownLatch doneSignal;
... RRSRunnable(final CountDownLatch doneSignal, final SaaSServerContext context,
final Map<String, List<JSONObject>> results, final String serverKey,
final MaxRecordCounter recordCounter)
{
this.doneSignal = doneSignal;
...
} @Override
public void run()
{
...
try
{
processRequest(responses, context.getHostName(), client, context, recordCounter);
final long elapsedTime = System.currentTimeMillis() - startTime;
XLog.fine("Traveler API request completed. orgid=" + orgId + ";request=" + reqUri + ";pool=" + serverKey
+ ";time=" + elapsedTime + "ms");
}
catch (final RestAPIException rae)
{
exceptionServerKey = serverKey;
exception = rae;
}
finally
{
doneSignal.countDown();
}
}
}
2.4 更加一般的Latch:
CountDownLatch是一种特殊的Latch,jcip第八章用countdownLatch实现了一种valueLatch。
2.4.1 nts Latch简介:
在nts生产代码中也实现了一种Latch,Latch允许多个线程间的协作:在这种Latch中,有working thread和latching thread之分:
workingThread在做一些工作,latchingThread希望当这些工作完成的时候,锁存这些工作,然后得到workingThread的工作结果。workingThread和latchingThread共享一个Latch对象,workingThread会调用start方法,通知它正在开始针对特定Object的工作已经开始了。同时,latchingThread将调用latch方法,并传进它希望等待的Object。 当workingThread完成对某一Object(start方法传入的)的工作后,它将调用finish方法,传入该对象,以及工作的结果对象。当finish方法被调用后,调用latch方法的线程被唤醒,返回工作结果给latch方法的调用者。多个线程可以锁存同一个将要完成某些工作的object。一旦任意一个线程调用了finish方法,他们都将被唤醒并返回结果对象。如果调用latch方法时,针对latch对象的工作还没有开始,线程立刻返回,并不会block. 所以start(Object)应该首先被调用。
workingThread调用start(Object)方法,表明它开始工作。 同时,latchingThread调用latch(Object,long)方法,等待workingThread的执行完成。 workingThread执行finish(Object,Object)方法,表示工作完成,此时,latchingThread醒来。start(Object) finish(Object,Object) --> working thread 第二个参数为结果。 ?
latch(Object,long) --> latching thread
2.4.2 nts Latch 实现:
start:
public boolean start(final Object obj)
{
final long timeStart = System.currentTimeMillis();
boolean rv = false;
Barrier b = null;
synchronized (this)
{
if (!latched.containsKey(obj))
{
b = new Barrier("Latch:" + name + "_Obj:" + obj, 1);
latched.put(obj, b); // latched is a synchronizedHashMap
rv = true;
}
}
XLog.exiting("name=" + name, "obj=" + obj, "barrier=" + b, "rv=" + rv, ("Elapsed time="
+ (System.currentTimeMillis() - timeStart) + "ms"));
return rv;
}
finish:
public void finish(final Object obj, final Object result)
{
final long timeStart = System.currentTimeMillis();
final Barrier b;
synchronized (this)
{
b = latched.remove(obj);
if (null != b)
{
// there are waiters that need the result
b.result = result;
try
{
b.enter(0);
}
catch (final InterruptedException e)
{
// ignored
}
}
}
XLog.exiting("name=" + name, "obj=" + obj, "result=" + result, "barrier=" + b, ("Elapsed time="
+ (System.currentTimeMillis() - timeStart) + "ms"));
}
3 CyclicBarrier
CountDownLatch一般用于某个线程A等待若干个其他线程执行完任务之后,它(一个线程)才执行; 而CyclicBarrier一般用于一组线程互相等待至某个状态,然后这一组线程再同时执行。
3.1 实现:
使用Lock和Condition实现。不同于AQS。(Condition是基于AQS实现的)
CyclicBarrier包含下面的域:
/** The lock for guarding barrier entry */
private final ReentrantLock lock = new ReentrantLock();
/** Condition to wait on until tripped */
private final Condition trip = lock.newCondition();
3.1.1 构造函数
当在等待栅栏的线程个数到达预定义的个数时,barrier 发生trip, 但是因为没有预定义的动作,所以不执行任何动作。
1 public CyclicBarrier(int parties) {
2 this(parties, null);
3 }
当barrier发生trip时,会由最后一个进入该barrier的线程执行特定的动作:
1 public CyclicBarrier(int parties, Runnable barrierAction) {
2 if (parties <= 0) throw new IllegalArgumentException();
3 this.parties = parties;
4 this.count = parties;
5 this.barrierCommand = barrierAction;
6 }
CyclicBarrier方法:
await():
public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L);
} catch (TimeoutException toe) {
throw new Error(toe); // cannot happen
}
}
await(Long time, TimeUtil unit):
1 public int await(long timeout, TimeUnit unit)
2 throws InterruptedException,
3 BrokenBarrierException,
4 TimeoutException {
5 return dowait(true, unit.toNanos(timeout));
6 }
上述两种方法都调用了dowait方法:
private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException,
TimeoutException {
final ReentrantLock lock = this.lock;
lock.lock();
try {
final Generation g = generation;
...
if (Thread.interrupted()) {
breakBarrier();
throw new InterruptedException();
} int index = --count;
if (index == 0) { // tripped
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
if (command != null)
command.run();
ranAction = true;
nextGeneration();
return 0;
} finally {
if (!ranAction)
breakBarrier();
}
} // loop until tripped, broken, interrupted, or timed out
for (;;) {
try {
if (!timed)
/* The lock associated with this Condition is atomically
released and the current thread becomes disabled for thread scheduling
purposes */
trip.await();
else if (nanos > 0L)
nanos = trip.awaitNanos(nanos);
} catch (InterruptedException ie) {
if (g == generation && ! g.broken) {
breakBarrier();
throw ie;
} else {
// We're about to finish waiting even if we had not
// been interrupted, so this interrupt is deemed to
// "belong" to subsequent execution.
Thread.currentThread().interrupt();
}
} if (g.broken)
throw new BrokenBarrierException(); if (g != generation)
return index; if (timed && nanos <= 0L) {
breakBarrier();
throw new TimeoutException();
}
}
} finally {
lock.unlock();
}
}
breakBarrier:
private void breakBarrier() {
generation.broken = true;
count = parties;
trip.signalAll();
}
3.2 使用:
在jdk和traveler code中没有使用。这符合Effective Java 69中的描述。在实际使用中较少见到。
4 Synchronizere与wait()/wait(long)/wait(long,int)/notify()/notifyAll()的比较:
在effective java 69中提到,wait()/wait(long)/wait(long,int)/notify()/notifyAll()不易使用且容易出错。一般来讲应该优选更高级的concurrent container 或者 synchronizer。 其中synchronizer比较常用的是Semaphore和CountDownLatch,而CyclicBarrier和Exchanger 则使用的比较少。说从易用性上来讲,wait()/notify()/notifyAll()更象是汇编语言,并发容器和synchronizer更像是高级语言。 但我在nts代码中看到了很多wait/notify,而Semaphore和CountDownLatch则用的很少。
Lock/Condition()是使用AQS实现的,Lock/Condition() 组合可以用来替代Object.wait()/notify()。 而高级的synchronizer: CountDownLatch& Semaphore也是基于AQS实现的。所以理论上,可以替代wait/notify。 Semaphore和CountDownLatch也都包含了跟wait(long timeout)相对应的方法。
考虑以下在下面的例子中,是否可以用Semaphore& CountDownLatch来代替wait/notify ?
public Connection getConnection(final boolean highpriority) throws SQLException
{
final long sTime = System.currentTimeMillis();
Connection conn = null;
boolean createConnection = false;
boolean waitConnection = false; try
{
while (true)
{
createConnection = false;
waitConnection = false; synchronized (dbConnections)
{ final List<Connection> dbConnectionsToBeFreedTemp = new ArrayList<Connection>();
synchronized (dbConnectionsToBeFreed)
{
if (!dbConnectionsToBeFreed.isEmpty())
{
dbConnectionsToBeFreedTemp.addAll(dbConnectionsToBeFreed);
dbConnectionsToBeFreed.clear();
if (1 == dbConnectionsToBeFreedTemp.size())
{
// only one, so only notify one
dbConnectionsToBeFreed.notify(); // Semaphore.release()
}
else
{
dbConnectionsToBeFreed.notifyAll(); // CountDownLatch.await()
}
}
if (isThrottDown && connectionCount <= Tier.ONE.value * .20F)
{
isThrottDown = false;
dbConnectionsToBeFreed.notifyAll();
}
} if (!dbConnectionsToBeFreedTemp.isEmpty())
{
for (final Connection connToFree : dbConnectionsToBeFreedTemp)
{
if (!closeConnectionIfAgedOut(connToFree))
{
dbConnections.add(connToFree);
}
}
dbConnectionsToBeFreedTemp.clear();
} if (Configuration.NTS_DB_CONNECTION_THROTTLING.getBoolean())
{
getCurrentTier(); if ((!dbConnections.isEmpty() && !isThrottDown)
&& (highpriority || ((connectionCount - dbConnections.size()) < currentTier.value))) //Prevent non-high priority requests from grabbing freed high priority connections if connection is capped
{
conn = dbConnections.remove(0);
} if (null == conn)
{
// See if we should create a new connection or have to wait
// if none are in the stack, then see if we should make another
if ((connectionCount < currentTier.value || (highpriority && (connectionCount < maxConnectionCount)))
&& !isThrottDown)
{ createConnection = true;
connectionCount++;
}
else if (!isScheduled && conn == null && !highpriority && !createConnection
&& currentTier != Tier.THREE && !isThrottDown)
{
WallClock.getInstance().addAlarm(ALARM_NAME,
Configuration.NTS_DB_POOL_STEP_INTERVAL_TIMER.getInt(), alarmStepUpTier);
isScheduled = true;
waitConnection = true;
}
else if (conn == null && !createConnection && currentTier == Tier.THREE
&& connectionCount - dbConnections.size() >= Tier.THREE.value && !isScheduled)
{
WallClock.getInstance().addAlarm(ALARM_THROTTLE_DOWN,
Configuration.NTS_DB_POOL_STEP_INTERVAL_TIMER.getInt(), alarmThrottleDown);
isScheduled = true;
waitConnection = true;
}
else
{
// Connections are maxed out, so we have to wait
waitConnection = true;
}
}
}
else
{
if (!dbConnections.isEmpty()
&& (highpriority || ((connectionCount - dbConnections.size()) <= maxConnectionCount)))
{
conn = dbConnections.remove(0);
} if (null == conn)
{
// See if we should create a new connection or have to wait
// if none are in the stack, then see if we should make another
if ((connectionCount < maxConnectionCount) || highpriority)
{ createConnection = true;
connectionCount++;
}
else
{
// Connections are maxed out, so we have to wait
waitConnection = true;
}
}
}
} if (null != conn)
{
// we have a Connection, so we are done
break;
}
else if (createConnection)
{
if (!isDerby)
{
// update user and password from Configuration
connProps.put("user", Configuration.NTS_DBUSER.getString());
connProps.put("password", Configuration.NTS_DBPASSWORD.getString());
} try
{
conn = DriverManager.getConnection(url, connProps);
}
catch (final SQLException sqle)
{
connectionCount--; // count must be decremented since a connection was never created
DatabaseStatus.reportException(sqle);
throw sqle;
} if (conn != null)
{
DatabaseStatus.clearException();
if (peakConnections < connectionCount)
{
peakConnections = connectionCount;
Stats.setStat(Stats.DB_POOL_PEAK_CONNECTIONS_COUNT, peakConnections);
Stats.setStat(Stats.DB_POOL_PEAK_CONNECTIONS_TIME, new Date().toString());
}
allConnections.put(Integer.valueOf(conn.hashCode()), PersistentStore.createDeathTimeStamp()); break;
}
else if (Configuration.NTS_DB_CONNECTION_THROTTLING.getBoolean())
{
// Unexpected Database exceptions will result in connection == null.
// Instead of retrying the connection, throw a checked exception.
throw new DBConnectionsAllUsedException("There are no DB Connections available");
}
else
{
// don't break which will do the retry
}
}
else if (waitConnection)
{
try
{
Stats.inc(Stats.DB_THREADS_WAITING_FOR_CONNECTION);
synchronized (dbConnectionsToBeFreed)
{
dbConnectionsToBeFreed.wait(); // Semaphore.acquire() CountDownLatch.countdown()
}
}
finally
{
Stats.dec(Stats.DB_THREADS_WAITING_FOR_CONNECTION);
}
// don't break which will do the retry
}
else
{
// should never hit this case
break;
}
}
}
catch (final InterruptedException ie)
{
// expected
throw new SQLException("Exception waiting for DB connection.", ie);
}
finally
{ } return conn;
}
5 进一步问题:
5.1 CyclicBarrier方法,await(): 为什么要提供这两种方法来包裹wrapper dowait方法?
5.2 Semaphore和CountDownLatch互换
final Semaphore sem = new Semaphore(0);
for (int i = 0; i < num_threads; ++ i)
{
Thread t = new Thread() {
public void run()
{
try
{
doStuff();
}
finally
{
sem.release();
}
}
};
t.start();
} sem.acquire(num_threads);
final CountDownLatch latch = new CountDownLatch(num_threads);
for (int i = 0; i < num_threads; ++ i)
{
Thread t = new Thread() {
public void run()
{
try
{
doStuff();
}
finally
{
latch.countDown();
}
}
};
t.start();
} latch.await();
6 参考文献:
http://www.cnblogs.com/dolphin0520/p/3920397.html
----- 单例 -----
单例与static方法的区别: 一个是实例,可以传递,另外一个不可以。(好像也没什么用,传递单例)。
http://stackoverflow.com/questions/519520/difference-between-static-class-and-singleton-pattern#
java并发之(4):Semaphore信号量、CounDownLatch计数锁存器和CyclicBarrier循环栅栏的更多相关文章
- java高并发系列 - 第17天:JUC中的循环栅栏CyclicBarrier常见的6种使用场景及代码示例
这是java高并发系列第17篇. 本文主要内容: 介绍CyclicBarrier 6个示例介绍CyclicBarrier的使用 对比CyclicBarrier和CountDownLatch Cycli ...
- 019-并发编程-java.util.concurrent之-Semaphore 信号量
一.概述 Semaphore是一个计数信号量.从概念上将,Semaphore包含一组许可证.如果有需要的话,每个acquire()方法都会阻塞,直到获取一个可用的许可证.每个release()方法都会 ...
- java并发之同步辅助类(Semphore、CountDownLatch、CyclicBarrier、Phaser)
线程同步辅助类,主要学习两点: 1.上述几种同步辅助类的作用以及常用的方法 2.适用场景,如果有适当的场景可以用到,那无疑是最好的 semaphore(seməˌfôr) 含义 信号量就是可以声明多把 ...
- Java多线程之Semaphore信号量
转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6557874.html 学过操作系统的对 信号量 这个词应该不陌生,它是用来进行进程间通信,控制对 临界区 ...
- 同步机制之--java CyclicBarrier 循环栅栏
CyclicBarrier介绍一个同步辅助类,它允许一组线程互相等待,直到到达某个公共屏障点 (common barrier point).在涉及一组固定大小的线程的程序中,这些线程必须不时地互相等待 ...
- Java并发之(3):锁
锁是并发编程中的重要概念,用来控制多个线程对同一资源的并发访问,在支持并发的编程语言中都有体现,比如c++ python等.本文主要讲解Java中的锁,或者说是重入锁.之所以这么说是因为在Java中, ...
- java并发之CountDownLatch、Semaphore和CyclicBarrier
JAVA并发包中有三个类用于同步一批线程的行为,分别是CountDownLatch.Semaphore和CyclicBarrier. CountDownLatch Java之CountDownLatc ...
- Java多线程系列--“JUC锁”11之 Semaphore信号量的原理和示例
概要 本章,我们对JUC包中的信号量Semaphore进行学习.内容包括:Semaphore简介Semaphore数据结构Semaphore源码分析(基于JDK1.7.0_40)Semaphore示例 ...
- Java并发之CountDownLatch、CyclicBarrier和Semaphore
CountDownLatch 是能使一组线程等另一组线程都跑完了再继续跑:CyclicBarrier 能够使一组线程在一个时间点上达到同步,可以是一起开始执行全部任务或者一部分任务. CountDow ...
随机推荐
- C++编写字符串类CNString,该类有默认构造函数、类的拷贝函数、类的析构函数及运算符重载
编码实现字符串类CNString,该类有默认构造函数.类的拷贝函数.类的析构函数及运算符重载,需实现以下“=”运算符.“+”运算.“[]”运算符.“<”运算符及“>”运算符及“==”运算符 ...
- HTML、CSS、JS、JQ速查笔记
一.HTML 1.编写html文件 a.格式 <!DOCTYPE html> <html> <head> <title>标题</title& ...
- linux 命令——56 ss(转)
ss是Socket Statistics的缩写.顾名思义,ss命令可以用来获取socket统计信息,它可以显示和netstat类似的内容.但ss的优势在于它能够显示更多更详细的有关TCP和连接状态的信 ...
- Aizu 0525 Osenbei(状压+贪心)
题意:翻煎饼,只能横着翻或者竖着翻.问最多有多少朝上? 行只有10,所以枚举一下2^10的状态,每列取0或1中最大的一个. 在枚举外面把饼翻好,枚举里面指针指一下就好.(位运算或bitset乱搞 #i ...
- 2018.6.24 oracle数据库的 事务及视图
第06章 事务及视图 本章内容 事务 视图 1 事务 1.1 什么是事务 事务也称工作单元,是一个或多个SQL语句组成的序列,这些个SQL操作作为一个完整的工作单元要么全部执行,要么全不执行. ...
- Linux学习记录(二)
1.远程连接工具的使用 实际开发中,Linux服务器都在其他的地方,我们要通过远程的方式去连接Linux并操作它,Linux远程的操作工具有很多,企业中常用的有Puttty.secureCRT.SSH ...
- 问题006:为什么用java.exe执行编译的类文件的时候,不这样写java Welcome.class
为什么用java.exe执行编译的类文件的时候,不这样写java Welcome.class 是因为java虚拟机调用Welcome的时候,已经替我们增减了.class,如果你还要写java Welc ...
- Vue 父组件传值到子组件
vue 父组件给子组件传值中 这里的AccessList就是子组件 如果 是静态传值的话直接 msg="xxx"就好 这里动态取值的话就 :msg=xxxxx ________ ...
- linux中管道(pipe)一谈
/*********************************************** 管道(pipe)是Linux上进程间通信的一种方式,其是半双工(数据流只能在一个方向上流动(还需要经过 ...
- mysql 5.7 编译安装脚本。
此脚本尽量运行在centos 服务器上面,用于编译安装mysql 5.7 将此脚本和相应的软件 都放到/usr/local/src 目录下面 由于不能上传附件 所以需要把cmake-3.9.6.ta ...