两个线程分别读写一个buffer,有没有办法不无名管道的阻塞型读写写buffer的那个线程

JAVA NIO 详解Buffer类
- 加俊 - ITeye技术网站
博客分类:
讲得很好,转载一下:/wiki/article/115-Xiang_Jie_Buffer_Class
Buffer类基本概念:
 一般而言,Buffer的数据结构是一个保存了原始数据的数组,在Java语言里面封装成为一
个带引用的对象。Buffer一般称为缓冲区,该缓冲区的优点在于它虽然是一个简单数组,但是它封装了很多数据常量以及单个对象的相关属性。针对
Buffer而言主要有四个主要的属性:
容 量(Capacity
容量描述了这个缓冲区最 多能够存放多少,也是Buffer的最大存储元素量,这个值是在创建Buffer的时候指定的,而且不可以更改
限 制(Limit
不能够进行读写的缓冲区 的第一个元素,换句话说就是这个Buffer里面的活动元素数量
位 置(Position
下一个需要进行读写的元 素的索引,当Buffer缓冲区调用相对get()和set()方法的时候会自动更新Position的值
一个可记忆的 Position位置的值,当调用mark()方法的时候会执行mark = position,一旦调用reset()的时候就执行position =
mark,和Position有点不一样,除非进行设置,否则Mark值是不存在的。
  按照上边的对应关系可以知道:
0 &= mark &= position &= limit &=
  这几个关系可以用下图进行描述:
  [1]Buffer的基本操 作:
  Buffer管理(Accessing):
  一般情况下Buffer可以管理很多元素,但是在程序开发过程中我们 只需要关注里面的活跃 元素
如上图小于limit位置的这些元素,因为这些元素是真正在IO读写过程需要的。当Buffer类调用了put()方法的时候,就在
原来的Buffer中插入了某个元素,而调用了get()方法过后就调用该位置的活跃元素,取出来进行读取,而Buffer的get和put方法一直很神
秘,因为它存在一个相对和绝对的概念:
  在相对版本
的put 和get
中,Buffer本身不使用index
作为参数,当相对方法调用的时候,直接使用position作为基点,然后运算 调用结果返回,在相对操作的时候,如果position的值过大就有可能抛出
信息;同样的相对版本的put方法调用的时候当调用元素超越了limit 的限制的时候也会抛出BufferOverflowException
,一般情况为:position
  在绝对版本
的put和 get
中,Buffer的position却不会收到影响,直接使用index
进行调用,如果index越界的时候直接抛出 Java里面常见的越界
:java.lang.
IndexOutOfBoundException
  针对get和put方法的两种版本的理解可以查阅API看看方法 get的定义【这里查 看的是Buffer类的子类ByteBuffer的API】
abstract byte
BufferUnderflowException
ByteBuffer get(byte
BufferUnderflowException
ByteBuffer get(byte
offset,int
BufferUnderflowException,IndexOutOfBoundException
abstract byte
IndexOutOfBoundException
从上边的API详解里面可以知道,Buffer本身支持的两种方式的访问是有原因
的,因为Buffer本身的设计目的是为了使得数据能够更加高效地传输,同样能够在某一个时刻移动某些数据。当使用一个数组作为参数的时候,整个
Buffer里面的
position位置放置了一个记录用的游标,该游标不断地在上一次操作完结的
进行移动来完成Buffer本身的数据的读取,这种情况下一般需要提
供一个length参数,使用该参数的目的就是为了防止越界操作的发生。如果请求的数据没有办法进行传输,当读取的时候没有任何数据能够读取的时候,这个
缓冲区状态就不能更改了,同时这个时候就会抛出BufferUnderflowException的
所以在向缓冲区请求的时候使用数组结构存储时,
如果没有指定length参数,系统会默认为填充整个数组的长度,这种情况和上边IO部分的缓冲区的设置方法类似。也就是说当编程过程需要将一个
Buffer数据拷贝到某个数组的时候(这里可以指代字节数组),需要显示指定拷贝的长度,否则该数组会填充到满,而且一旦当满足
条件:即limit 和position不匹配的时候,就会抛
  [2]Buffer填充 (Filling):
  先看一段填充ByteBuffer的代码:
buffer.put((byte
).put((byte
).put((byte
).put((byte
).put((byte
  当这些字符传入的时候都是以ASCII值存储的,上述操作的存储步骤图如下:
  这里需要留意一点就是填充的时候需要进行强制转换
, 因为Java里面所有的字符格式都是16bit的Unicode格式
,而上边代码里面填充的时候使用的参数是字符的,如果不进行强制转换会出现数据丢失
的情 况,ASCII码表示字符的时候使用的是8位数据,而Unicode方式保存字符本身和ASCII保存有很大的区别,为了不出现乱码保证存储到缓冲区字符 的正确性,一定记住需要进行强制换转,转换成为对应的字节方式保存。再继续针对该Buffer进行填充操作:
buffer.put(0,(byte
).put((byte
  第一个方法使用了绝对的方式使用index参数替换了缓冲区中的第一个字节,而第二个使用了相对版本的put方 法,所以最终形成的Buffer存储结构图为:
  从上边两个操作可以知道,Buffer类在填充该Buffer的时候使用相对方法 和绝对方法有很大的区别,上图可以看到原来存入的“Hello”
现在变成了“Mellow”
,这就是Buffer填充操作的一个缩略图。
  [3]Buffer的反转(Flipping)
  当我们在编程过程中填充了一个Buffer过后,就会对该Buffer进行消耗 (Draining)
操作,一般是将该Buffer传入一个通道(Channel)
内 然后输出。但是在Buffer传入到通道中过后,通道会调用get()方法来获取Buffer里面数据,但是Buffer传入的时候是按照顺序传入到通道 里面的,如上边的结构可以知道,本身存储的数据可能为“Mellow”
,但是当通道读取Buffer里面的内容的时候,有可能取到不正确的数据,原因 在于通道读取Buffer里面的数据的时候标记是从右边开始的,这样读取的数据如果从position开始就会有
【*:当然不排除有这样一种情况缓 冲区提供了读取策略是双向的,那么这样读取出来的所有的字符就有可能是反向的】
。其实这点概念很容易理解,因为Buffer读取过后会按照 顺序读入到通道(Channel)
中,而通道获取数据的时候会从最右边的position位 置
开始,所以针对这样的情况如果需要正确读取里面的内容就需要对Buffer进行反转操作
,该操作的手 动代码如下:
buffer.limit(buffer.position()).position(0);
  但是因为Java中Buffer类的API提供了类似的操作,只需要下边的方法就可以了:
buffer.flip();
  经过flip操作过后,其存储结构就会发生相对应的变化:
  【*:这个地方仔细想想,经过了Flip操作过后,从逻辑意义上讲,确实 Buffer被反转了,因为这个时候通道类(Channel)读取Buffer的时候会从position地方继续读取,不会出现读取
的情况。与其说 是
,不如说是“重置”
,只是这里的“重置”
不 会清空缓冲区里面的数据,仅仅是
将缓冲区的limit属性和position属性进行重设
,和真正调用reset方法的 时候还是存在一定区别的,至于这里Flip翻译称为“反转”
我不做说明,只要读者能够理解上边的步骤而且 知道这是一次Flip操作就可以了,这里正确理解的是“重置position”
我们在编程中也经常看见 rewind()方法,该方法和flip()类似,但是该方法不会影响到limit的变化,它仅仅会将position设置为0,所以可以直接使用 rewind方法进行
“重新读取”
还需要说明一点是如果进行了两次flip()操作
的话, 第二次操作会同时将 position和limit设置为0
,这样的话如果再进行基于缓冲区的相对读取过程就会BufferOverflowException
  [4]Buffer的“消费”(Draining):
  当一个Buffer缓冲区填满数据过后,应用程序就会将该缓冲区送入一个通道内进行“消费”
, 这种“消 费”
操作实际上使用通道来读取Buffer里面存储的数据,如果需要读取任何一个位置上的元素,则需要先flip操作才 能够顺利接受到该Buffer里面的元素数据,也就是说在Channel通道调用get()方法之前先调用flip()方法
,【*:这里这种方式的调用是相 对调用过程,从参数可以知道,这里的get()是相对方法的常用调用方式】
在通道“消费”
Buffer 的过程中,有可能会使得position达到limit,不过Buffer类有一个判断方法hasRemaining()
, 该方法会告诉程序position 是否达到了limit
,因为position一旦超越了limit过后会抛出BufferOverflowException
异 常,所以最好在迭代读取Buffer里面的内容的时候进行判断,同时Buffer类还提供了一个remaining()方法返回目前的limit的值。
  *:Buffer并不是
安全的,如果需要多
操作一个Buffer,需要自己定义同步来操作 Buffer,
提供一个相关例子:
  ——[$]
Fill和Drain两个方法代码例子——
org.susan.java.
java.nio.CharB
public class
BufferFillDrain {
private static int
index = 0;
private static
[] strings = {
"A random string value",
"The product of an infinite number of
"Hey hey we're the Monkees",
"Opening act for the Monkees: Jimi
"'Scuse me while I kiss this fly'",
"Help Me! Help Me!"
private static void
drainBuffer(CharBuffer
(buffer.hasRemaining()){
System.out
.print(buffer.get());
System.out
.println();
private static boolean
fillBuffer(CharBuffer buffer){
( index &= strings.length)
return false
string = strings[index++];
= 0; i & string.length(); i++ )
buffer.put(string.charAt(i));
return true
public static void
main(String args[])
Exception{
CharBuffer buffer = CharBuffer.allocate
(fillBuffer(buffer)){
buffer.flip();
drainBuffer
buffer.clear();
  该方法的输出如下:
A random string value
The product of an infinite number of monkeys
Hey hey we're the Monkees
Opening act for the Monkees: Jimi Hendrix
'Scuse me while I kiss this fly'
Help Me! Help Me!
  【*:这段输出其实看不出来什么
的效率明显胜过IO,这个是可以通过一些
的例 子来证明的。】
  当一个Buffer进行了Fill和Drain操作过后,如果需要重新使用该Buffer,就 可以使用reset()方法,这里reset()就是清空数据并且重置该Buffer,对比上边的Flip()操作的“重置position”
就 很容易理解Buffer的使用过程了。这里列举了很多方法,防止混淆摘录Java
API里面的Buffer抽象类的所有方法列表,这是抽象类Buffer里面的所有方法列表,上边介绍的方法若没有在此出现则就应该在它的子类中:
public abstract
Object array():
返回底 层缓冲区的实现数组
public abstract int
arrayOffset():
返回该缓冲区底层实现数 组的偏移量
public int
capacity():
返回该缓冲区的容量
Buffer clear():清除
Buffer flip():反转
public abstract boolean
hasArray():
判断该缓冲区是否有可访问的底 层实现数组
public abstract boolean
hasRemaining():
判断该 缓冲区在当前位置和限 制
之间是否有元素
public abstract boolean
isDirect():
判断该缓冲区是否为直接缓冲区
public abstract boolean
isReadOnly():
判断该缓冲区是否为只读缓冲区
public int
返回该缓冲区的限制
Buffer limit(int
newLimit):
设置此缓冲区的限制
Buffer mark():
在此缓冲区的位置设置标记
public int
position():
返回此缓冲区的位置
Buffer position(int
newPosition):
设置此缓冲区的位置
public int
remaining():
返回当前位置与限制之间的元素数
Buffer reset():
将此缓 冲区的位置重置为以前标 记的位置
Buffer rewind():
重绕 此缓冲区
  [5]Buffer的压缩(Compacting):
  很多时候,应用程序有可能只需要从缓冲区中读取某一部分内容而不需要读取所有,而有时候又需要 从原来的位置重新填充,为了能够进行这样的操作,那些不需要读取的数据要从缓冲区中清除掉,这样才能使得第一个读取到的元素的索引变成0,这种情况下就需 要使用compact()
操 作来完成,这个方法从上边Buffer类的列表中可以知道并不包含该方法,但是每个Buffer子类实现里面都包含了这个方法,使用该方法进行所需要的读 取比使用get()
更 加高效,但是这种情况只在于读取部分缓冲区内的内容。这里分析一个简单的例子:
  当上边这样的情况使用了 pact()
操作后,情况会演变成下边这种样子:
  【*:仔细分析上边的内容,究竟发生了什么事情呢?上边这一段将可以读取到的
拷贝到了索引0-3的位 置,而4和5成为了不可读的部分,但是继续移动position仍然可以读取到但是它们这些元素已经“死亡”
了, 当调用put()方法的时候,它们就会被
掉,而且limit设置到 了容量位置,则该Buffer就可以重新被完全填充。当Buffer调用了compact方法过后将会放弃已经消费过的元素,而且使得该Buffer可以 重新填充,
这种方式类似一个先进先出的队列(FIFO)
可以这样理解,compact()方法将position和limit之间的
数据复制到开始位置,从而为后续的put()/read()让出空间,position的值设置为要赋值的数组的长度,limit值为容量,这里摘录一段
网上讲解的compact方法的使用场景:
果有一个缓冲区需要写数据,write()方法的非阻塞调用只会写出其能够发送的数据而不会阻塞等待所有的数据都发
送完成,因此write()方法不一定会将缓冲区中所有的元素都发出去,又假设现在需要调用read()方法,在缓冲区中没有发送的数据后面读入新数据,
处理方法就是设置
position = limit 和 limit = capacity
,当然在读入新数据后,再次调用 write()方法前还需要将这些值还原,这样做就会使得缓冲区最终耗尽,这就是该方法需要解决的主要
  [6]Buffer的标记(Marking):
  标记方法mark()使得该Buffer能够记住某个位置并且让position在返回的时候不用返回初始索 引0而直接返回标记处进行操作
,若mark没有定义,调用reset()方法将会抛出InvalidMarkException
,需要注意的是不要混淆reset()方法和clear()方法,clear()方法单纯清空该Buffer里面的元素,而reset()方法在清空
上还会重新设置一个Buffer的四个对应的属性
,其实Marking很好理解,提供一段代码和对应的图示:
buffer.position(2).mark().position(4);
当上边的buffer调用了方法reset过后:
  如上边所讲,position最终回到了mark处而不是索引为0的 位置
  [7]Buffer的比较 (Comparing):
  在很多场景,有必要针对两个缓冲区进行比较操作,所有的Buffer 都提供了equals()方法用来比较两个Buffer,而且提供了compareTo()方法进行比较。既然是两个Buffer进行比较,它们的比较条 件为:
两 个对象应该是
的,Buffer包含了
不同的数据类型就绝对不可能相等
两 个Buffer对象position到limit之间的元素数量(remaining返回值)相同,两个Buffer的
容量可以不一样
,而且两个Buffer的
索引位置也可以不一样
,但是Buffer的remaining(从 position到limit)方法返回值必须是相同的
从remaining段的出示位置到结束位置里面的每一个元素都
必 须相 同
  两个相同Buffer图示为(equals()返回true
  两个不相同的Buffer图示为(equals() 返回为false
  最后针对Buffer简单总结一下,ByteBuffer里面的Big- Endian和Little-Endian
已经在《Java
模型》章节介绍了这里不重复。
浏览 13624
iammonster
浏览: 1270102 次
来自: 北京
例子都打不开
好东西[color=blue][/color]
不在haoop中是在linux系统中,映射IP的时候,不能使用 ...
挺好的, 谢谢分享帐号:密码:下次自动登录{url:/nForum/slist.json?uid=guest&root=list-section}{url:/nForum/nlist.json?uid=guest&root=list-section}
贴数:1&分页:秋雨☆Dull Days,Blue Nights...发信人: trueice (秋雨☆Dull Days,Blue Nights...), 信区: LinuxDev
标&&题: [合集] 两个线程读写互斥的办法
发信站: 水木社区 (Wed Aug 31 14:50:14 2005), 站内 && ☆─────────────────────────────────────☆ &&
rivertomoon (rivertomoon) 于
(Thu Aug 25 16:37:32 2005)
提到: && typedef struct tQUEUE
{ &&&&&&&&PACKET * first_ &&&&&&&&PACKET * last_
}QUEUE; && typedef struct tPACKET
{ &&&&&&&& &&&&&&&&int left_ &&&&&&&&struct timeval arrive_ &&&&&&&&struct timeval depart_ &&&&&&&&float&& &&&&&&&&struct tPACKET *
}PACKET; && 这样定义一个队列以及其节点。有两个进程。一个写、一个读。
除了每次读写加锁,解锁。这样来保证读写安全,有没有别的办法?
因为一个进程在队头读,一个在队尾写。大部分情况不会有问题,能不能有办法不要每次都加解锁。 && 不想用Linux自己的消息队列,因为好象一旦读出来,就没办法按原位置写进去了 &&&& ☆─────────────────────────────────────☆ &&
icubaby (juny) 于
(Thu Aug 25 20:29:20 2005)
提到: && 我觉得,每次读写还是要加锁或者是解锁,这样才可以保证线程的同步。性能上,没什么损失嘛。 && 【 在 rivertomoon (rivertomoon) 的大作中提到: 】
: typedef struct tQUEUE
:&&&&&&&&PACKET * first_
: ...................
&&&&&& ☆─────────────────────────────────────☆ &&
paranoia (幽灵) 于
(Thu Aug 25 20:47:16 2005)
提到: &&&& ring buffer? && 【 在 rivertomoon (rivertomoon) 的大作中提到: 】
: typedef struct tQUEUE
:&&&&&&&&PACKET * first_
: ...................
&&&&&& ☆─────────────────────────────────────☆ &&
I0O (百分百假上进白萝卜的乖乖萝卜妹) 于
(Thu Aug 25 20:53:00 2005)
提到: && ring buffer也不解决问题吧.
我觉得如果没有什么特殊原因
只是觉得锁不爽而不用的话是
很不明智的选择. && 【 在 paranoia (幽灵) 的大作中提到: 】
: ring buffer?
&&&&&&&& ☆─────────────────────────────────────☆ &&
paranoia (幽灵) 于
(Thu Aug 25 20:56:21 2005)
提到: && 只有一个读一个写,还不够? &&&& 【 在 I0O (百分百假上进白萝卜的乖乖萝卜妹) 的大作中提到: 】
: ring buffer也不解决问题吧.
: 我觉得如果没有什么特殊原因
: 只是觉得锁不爽而不用的话是
: ...................
&&&&&& ☆─────────────────────────────────────☆ &&
I0O (百分百假上进白萝卜的乖乖萝卜妹) 于
(Thu Aug 25 20:58:37 2005)
提到: && ring只是结构吧,ring比不ring有更复杂的同步需求吧. && 【 在 paranoia (幽灵) 的大作中提到: 】
: 只有一个读一个写,还不够?
&&&&&&&& ☆─────────────────────────────────────☆ &&
paranoia (幽灵) 于
(Thu Aug 25 21:08:18 2005)
提到: && 愿闻其祥 &&&& 【 在 I0O (百分百假上进白萝卜的乖乖萝卜妹) 的大作中提到: 】
: ring只是结构吧,ring比不ring有更复杂的同步需求吧.
&&&&&&&& ☆─────────────────────────────────────☆ &&
I0O (百分百假上进白萝卜的乖乖萝卜妹) 于
(Thu Aug 25 21:44:15 2005)
提到: && 这个,没啥好详的吧.......
ring对这个问题有啥帮助阿? && 维护队列俨然比ring要简单一些
至少不用太考虑头尾交会的问题
这个还是不解决万一内容空了,
尾巴和头相与而产生的访问冲突阿 && 【 在 paranoia (幽灵) 的大作中提到: 】
: 愿闻其祥
&&&&&&&& ☆─────────────────────────────────────☆ &&
weakmaster (听说我是瓶子,我要做漂流瓶) 于
(Thu Aug 25 22:28:27 2005)
提到: && 性能没有什么影响
头和尾只是相对的
【 在 rivertomoon (rivertomoon) 的大作中提到: 】
: typedef struct tQUEUE
:&&&&&&&&PACKET * first_
: ...................
&&&&&& ☆─────────────────────────────────────☆ &&
laws (law) 于
(Fri Aug 26 08:38:33 2005)
提到: && 必须加,而且应该加在struct tQUEUE上
因为你每次读和写都要修改同一个
struct tQUEUE。
【 在 rivertomoon (rivertomoon) 的大作中提到: 】
: typedef struct tQUEUE
:&&&&&&&&PACKET * first_
: ...................
&&&&&&&&&& ☆─────────────────────────────────────☆ &&
rivertomoon (rivertomoon) 于
(Fri Aug 26 09:10:21 2005)
提到: && 谢谢各位热心的讨论和意见 && 【 在 laws (law) 的大作中提到: 】
: 必须加,而且应该加在struct tQUEUE上
: 因为你每次读和写都要修改同一个
: struct tQUEUE。
&&&&&&&&&& ☆─────────────────────────────────────☆ &&
paranoia (幽灵) 于
(Fri Aug 26 10:21:43 2005)
提到: &&&& 有没有办法不锁的?
条件是一个读一个写 && 【 在 laws (law) 的大作中提到: 】
: 必须加,而且应该加在struct tQUEUE上
: 因为你每次读和写都要修改同一个
: struct tQUEUE。
: ...................
&&&&&& ☆─────────────────────────────────────☆ &&
scircle (缘) 于
(Fri Aug 26 11:18:24 2005)
提到: && 读写锁 && 【 在 paranoia (幽灵) 的大作中提到: 】
: 有没有办法不锁的?
: 条件是一个读一个写
&&&&&&&& ☆─────────────────────────────────────☆ &&
paranoia (幽灵) 于
(Fri Aug 26 11:24:35 2005)
提到: &&&& 一个读一个写就有必要用读写锁吗 && 【 在 scircle (缘) 的大作中提到: 】
&&&&&&&& ☆─────────────────────────────────────☆ &&
scaner (eca-464f-9b0e-13a3a9e97384) 于
(Fri Aug 26 11:25:39 2005)
提到: &&&& 你要是铁板钉钉保证队列里面至少有一个以上的数据
那就没有必要. && 【 在 paranoia (幽灵) 的大作中提到: 】
: 一个读一个写就有必要用读写锁吗
&&&&&&&& ☆─────────────────────────────────────☆ &&
paranoia (幽灵) 于
(Fri Aug 26 11:27:56 2005)
提到: &&&& 清楚了…… && 谢谢 && 【 在 scaner (eca-464f-9b0e-13a3a9e97384) 的大作中提到: 】
: 你要是铁板钉钉保证队列里面至少有一个以上的数据
: 那就没有必要.
&&&&&&&& ☆─────────────────────────────────────☆ &&
laws (law) 于
(Fri Aug 26 11:50:31 2005)
提到: && no,如果是队列,读和写会同时操作队列数据结构,
光加读写锁是不够的,不管你队列里有多少数据。
【 在 scaner (eca-464f-9b0e-13a3a9e97384) 的大作中提到: 】
: 你要是铁板钉钉保证队列里面至少有一个以上的数据
: 那就没有必要.
&&&&&&&&&& ☆─────────────────────────────────────☆ &&
laws (law) 于
(Fri Aug 26 11:52:32 2005)
提到: && 读写锁对他那个不合适,
有可能仔细设计以后用atomic加或者减来同步,但
很多时候atomic op不一定比NPTL的同步原语效率高。
【 在 scircle (缘) 的大作中提到: 】
&&&&&&&&&& ☆─────────────────────────────────────☆ &&
paranoia (幽灵) 于
(Fri Aug 26 12:10:21 2005)
提到: &&&& user space 怎么用atomic加减? && 【 在 laws (law) 的大作中提到: 】
: 读写锁对他那个不合适,
: 有可能仔细设计以后用atomic加或者减来同步,但
: 很多时候atomic op不一定比NPTL的同步原语效率高。
: ...................
&&&&&& ☆─────────────────────────────────────☆ &&
scaner (eca-464f-9b0e-13a3a9e97384) 于
(Fri Aug 26 12:11:12 2005)
提到: && 可以阿,写队列之修改头
读队列只修改尾巴
只要中间有数据
头和尾巴就不会是一个数据结构阿 &&&& 【 在 laws (law) 的大作中提到: 】
: no,如果是队列,读和写会同时操作队列数据结构,
: 光加读写锁是不够的,不管你队列里有多少数据。
&&&&&&&& ☆─────────────────────────────────────☆ &&
paranoia (幽灵) 于
(Fri Aug 26 13:01:32 2005)
提到: &&&& 同意
不过有哪些情况是队列中始终有数据呢? && 【 在 scaner (eca-464f-9b0e-13a3a9e97384) 的大作中提到: 】
: 可以阿,写队列之修改头
: 读队列只修改尾巴
: 只要中间有数据
: ...................
&&&&&& ☆─────────────────────────────────────☆ &&
laws (law) 于
(Fri Aug 26 13:14:04 2005)
提到: && 那是没想好在乱讲,你同意啥。
你怎么实现头只会加的buffer?而不去读尾?&& ring-buffer你不读尾巴能知道队列有多长?
同样操作尾的时候你不去读头,
如何知道队列是否满了,或者是空了。
【 在 paranoia (幽灵) 的大作中提到: 】
: 不过有哪些情况是队列中始终有数据呢?
&&&&&&&&&& ☆─────────────────────────────────────☆ &&
igmp (心茫然-有情有义,敢爱敢恨) 于
(Fri Aug 26 13:20:20 2005)
提到: && 怎么越说越乱了啊。
就两个线程同步的问题。
用ring-buffer很好啊,
就是不能动态增减buffer的长度 && 【 在 laws (law) 的大作中提到: 】
: 那是没想好在乱讲,你同意啥。
: 你怎么实现头只会加的buffer?而不去读尾?&&
: ring-buffer你不读尾巴能知道队列有多长?
: ...................
&&&&&& ☆─────────────────────────────────────☆ &&
paranoia (幽灵) 于
(Fri Aug 26 13:26:51 2005)
提到: &&&& 汗…… && 他说的不是队列吗?
ring buffer是我说的
队列和ring buffer没有必然联系吧 && 【 在 laws (law) 的大作中提到: 】
: 那是没想好在乱讲,你同意啥。
: 你怎么实现头只会加的buffer?而不去读尾?&&
: ring-buffer你不读尾巴能知道队列有多长?
: ...................
&&&&&& ☆─────────────────────────────────────☆ &&
laws (law) 于
(Fri Aug 26 13:57:58 2005)
提到: && 队列?
你用伪代码示例一下,
如何操作?
【 在 paranoia (幽灵) 的大作中提到: 】
: 他说的不是队列吗?
: ring buffer是我说的
: ...................
&&&&&&&&&& ☆─────────────────────────────────────☆ &&
paranoia (幽灵) 于
(Fri Aug 26 14:00:12 2005)
提到: &&&& 他的意思是说如果确定队列中元素个数肯定多于一个
那么读写指针指向的肯定不是一个位置,那么就没问题了 && 貌似是这样的 &&&&&& 【 在 laws (law) 的大作中提到: 】
: 你用伪代码示例一下,
: 如何操作?
: ...................
&&&&&& ☆─────────────────────────────────────☆ &&
shongyi (naive) 于
(Fri Aug 26 14:12:25 2005)
提到: && semaphore可以
【 在 rivertomoon (rivertomoon) 的大作中提到: 】
: typedef struct tQUEUE
:&&&&&&&&PACKET * first_
: ...................
&&&&&& ☆─────────────────────────────────────☆ &&
laws (law) 于
(Fri Aug 26 14:14:53 2005)
提到: && 先不说如何不同时读队列头尾来判断里面元素个数。 && 你队列难道是无限长?
头只加不减, 或者只减不加? && 【 在 paranoia (幽灵) 的大作中提到: 】
: 他的意思是说如果确定队列中元素个数肯定多于一个
: 那么读写指针指向的肯定不是一个位置,那么就没问题了
: 貌似是这样的
&&&&&&&&&& ☆─────────────────────────────────────☆ &&
paranoia (幽灵) 于
(Fri Aug 26 14:26:43 2005)
提到: &&&& :) && 只是假设吗
本来保证队列中元素肯定大于一个就不太可能 && 不过话说回来
ring buffer似乎可以,ldd3这么说的……
不知道是不是理解的有问题 && 【 在 laws (law) 的大作中提到: 】
: 先不说如何不同时读队列头尾来判断里面元素个数。
: 你队列难道是无限长?
: 头只加不减, 或者只减不加?
: ...................
&&&&&& ☆─────────────────────────────────────☆ &&
laws (law) 于
(Fri Aug 26 14:36:41 2005)
提到: && ldd3里哪章这么说,
找出来,如果真那么说了。
俺帮你去扁Greh, Kroah
【 在 paranoia (幽灵) 的大作中提到: 】
: 只是假设吗
: 本来保证队列中元素肯定大于一个就不太可能
: ...................
&&&&&&&&&& ☆─────────────────────────────────────☆ &&
paranoia (幽灵) 于
(Fri Aug 26 14:55:55 2005)
提到: && ch5
Lock-Free Algorithms
不知道是不是理解错了 && 【 在 laws (law) 的大作中提到: 】
: ldd3里哪章这么说,
: 找出来,如果真那么说了。
: 俺帮你去扁Greh, Kroah
: ...................
&&&&&& ☆─────────────────────────────────────☆ &&
laws (law) 于
(Fri Aug 26 15:08:18 2005)
提到: &&&& 他说的那种实现需要把所有的inc和dec操作弄成atomic的,
你仔细看他例子里举的kfifo.h,对外可见的操作都是用spinlock锁住的。 && 【 在 paranoia (幽灵) 的大作中提到: 】
: Lock-Free Algorithms
: 不知道是不是理解错了
&&&&&&&&&& ☆─────────────────────────────────────☆ &&
paranoia (幽灵) 于
(Fri Aug 26 15:11:17 2005)
提到: && 明白了
什么情况下inc dec不是atomic的?
wrap? &&&& 【 在 laws (law) 的大作中提到: 】
: 他说的那种实现需要把所有的inc和dec操作弄成atomic的,
: 你仔细看他例子里举的kfifo.h,对外可见的操作都是用spinlock锁住的。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ && 注释里面说保护并发更改,也就是对in和out的操作把 &&&&&&&& ☆─────────────────────────────────────☆ &&
igmp (心茫然-有情有义,敢爱敢恨) 于
(Fri Aug 26 15:29:03 2005)
提到: && 浪费一个元素就可以
满的时候只有n-1各有用 && 【 在 paranoia (幽灵) 的大作中提到: 】
: 只是假设吗
: 本来保证队列中元素肯定大于一个就不太可能
: ...................
&&&&&& ☆─────────────────────────────────────☆ &&
deem (沙丘男爵) 于
(Fri Aug 26 16:29:21 2005)
提到: &&&& ring buffer 转起来的时候就不浪费了,就是初始化的浪费一个。 && ring buffer 肯定可以lock free的,我做过。 && 【 在 igmp (心茫然-有情有义,敢爱敢恨) 的大作中提到: 】
: 浪费一个元素就可以
: n各元素,
: 满的时候只有n-1各有用
: ...................
&&&&&& ☆─────────────────────────────────────☆ &&
weakmaster (听说我是瓶子,我要做漂流瓶) 于
(Fri Aug 26 16:45:52 2005)
提到: && 哈哈哈哈,该扁
【 在 laws (law) 的大作中提到: 】
: ldd3里哪章这么说,
: 找出来,如果真那么说了。
: 俺帮你去扁Greh, Kroah
: ...................
&&&&&& ☆─────────────────────────────────────☆ &&
paranoia (幽灵) 于
(Fri Aug 26 16:49:14 2005)
提到: && 不过ldd3提到的kfifo确实用到了spinlock
在up上是不是不用理会? &&&& 【 在 deem (沙丘男爵) 的大作中提到: 】
: ring buffer 转起来的时候就不浪费了,就是初始化的浪费一个。
: ring buffer 肯定可以lock free的,我做过。
&&&&&&&& ☆─────────────────────────────────────☆ &&
rivertomoon (rivertomoon) 于
(Fri Aug 26 22:42:20 2005)
提到: && 呵呵,谢谢大家了。
翻了一下数据结构的书,ring buffer应该可以不用锁。
没太深的计算机的背景,什么原子操作不太明白。 && 我这里的“读”,事实是数据出队列的过程 &&&& ☆─────────────────────────────────────☆ &&
weakmaster (听说我是瓶子,我要做漂流瓶) 于
(Fri Aug 26 22:43:11 2005)
提到: && 和数据结构没关系
好好看看操作系统
【 在 rivertomoon (rivertomoon) 的大作中提到: 】
: 呵呵,谢谢大家了。
: 翻了一下数据结构的书,ring buffer应该可以不用锁。
: 没太深的计算机的背景,什么原子操作不太明白。
: ...................
&&&&&& 文章数:1&分页:
抽奖到手软!将狂欢进行到底!

我要回帖

更多关于 stringbuffer线程安全 的文章

 

随机推荐