??xml version="1.0" encoding="utf-8" standalone="yes"?> 对于刚刚接触Linux的h来说Q一定会(x)lLinux下一大堆各式各样的文件名l搞晕。别个不_(d)单单压~文件ؓ(f)例,我们知道在Windows?
最常见的压~文件就只有两种Q一?zipQ另一个是.rap。可是Linux׃同了Q它?gz?tar.gz、tgz、bz2?Z?tar{?
众多的压~文件名Q此外windows下的.zip?rar也可以在Linux下用,不过在Linux使用.zip?rar的h太了。本文就?
对这些常见的压羃文gq行一番小l,希望你下ơ遇到这些文件时不至于被搞晕:) 在具体ȝ各类压羃文g之前呢,首先?
弄清两个概念Q打包和压羃。打包是指将一大堆文g或目录什么的变成一个ȝ文gQ压~则是将一个大的文仉过一些压~算法变成一个小文g。ؓ(f)什么要区分q?
两个概念呢?其实q源于Linux中的很多压羃E序只能针对一个文件进行压~,q样当你惌压羃一大堆文gӞ你就得先借助另它的工具将q一大堆文g先打
成一个包Q然后再原来的压羃E序q行压羃?br />
Linux下最常用的打包程序就是tar了,使用tarE序打出来的包我们常UCؓ(f)tar
包,tar包文件的命o(h)通常都是?tarl尾的。生成tar包后Q就可以用其它的E序来进行压~了Q所以首先就来讲讲tar命o(h)的基本用法:(x) # tar -tf all.tar compress也是一个压~程序,但是好象使用compress的h不如gzip和bzip2的h多?Zl尾的文件就是bzip2压羃的结
果。与compress相对的解压程序是uncompress。tar中?Zq个参数来调用gzip。下面来举例说明一下:(x) # unzip all.zip 2)对于.rar
Linux下的压羃文g剖析
tar命o(h)的选项有很?用man tar可以查看?Q但常用的就那么几个选项Q下面来举例说明一下:(x)
# tar -cf
all.tar *.jpg
q条命o(h)是将所?jpg的文件打成一个名为all.tar的包?c是表CZ生新的包Q?f指定包的文g名?br />
# tar -rf all.tar *.gif
q条命o(h)是将所?gif的文件增加到all.tar的包里面厅R?r是表C增加文件的?
思?br />
# tar -uf all.tar logo.gif
q条命o(h)是更新原来tar包all.tar中logo.gif?
Ӟ-u是表C更新文件的意思?
q条命o(h)是列出all.tar包中所有文Ӟ-t是列出文件的意?br />
# tar
-xf all.tar
q条命o(h)是解出all.tar包中所有文Ӟ-t是解开的意?br />
以上是tar的最基本的用法。ؓ(f)了方便用
户在打包解包的同时可以压~或解压文gQtar提供了一U特D的功能。这是tar可以在打包或解包的同时调用其它的压羃E序Q比如调用gzip?
bzip2{?br />
1) tar调用gzip
gzip是GNUl织开发的一个压~程序,.gzl尾的文件就是gzip压羃的结果。与
gzip相对的解压程序是gunzip。tar中?zq个参数来调用gzip。下面来举例说明一下:(x)
# tar -czf
all.tar.gz *.jpg
q条命o(h)是将所?jpg的文件打成一个tar包,q且其用gzip压羃Q生成一个gzip压羃q的包,
包名为all.tar.gz
# tar -xzf all.tar.gz
q条命o(h)是将上面产生的包解开?br />
2)
tar调用bzip2
bzip2是一个压~能力更强的压羃E序Q?bz2l尾的文件就是bzip2压羃的结果。与bzip2相对的解压程序是
bunzip2。tar中?jq个参数来调用gzip。下面来举例说明一下:(x)
# tar -cjf all.tar.bz2 *.jpg
q条命o(h)是将所?jpg的文件打成一个tar包,q且其用bzip2压羃Q生成一个bzip2压羃q的包,包名为all.tar.bz2
# tar -xjf all.tar.bz2
q条命o(h)是将上面产生的包解开?br />
3)tar调用compress
# tar
-cZf all.tar.Z *.jpg
q条命o(h)是将所?jpg的文件打成一个tar包,q且其用compress压羃Q生成一?
uncompress压羃q的包,包名为all.tar.Z
# tar -xZf all.tar.Z
q条命o(h)是将上面产生的包
解开
有了上面的知识,你应该可以解开多种压羃文g了,下面对于tarpd的压~文件作一个小l:(x)
1)对于.tarl尾的文?br />
tar -xf all.tar
2)对于.gzl尾的文?br />
gzip -d all.gz
gunzip
all.gz
3)对于.tgz?tar.gzl尾的文?br />
tar -xzf all.tar.gz
tar -xzf
all.tgz
4)对于.bz2l尾的文?br />
bzip2 -d all.bz2
bunzip2 all.bz2
5)对于tar.bz2l尾的文?br />
tar -xjf all.tar.bz2
6)对于.Zl尾的文?br />
uncompress all.Z
7)对于.tar.Zl尾的文?br />
tar -xZf all.tar.z
另外对于
Window下的常见压羃文g.zip?rarQLinux也有相应的方法来解压它们Q?br />
1)对于.zip
linux下提供了
zip和unzipE序Qzip是压~程序,unzip是解压程序。它们的参数选项很多Q这里只做简单介l,依旧举例说明一下其用法Q?br />
#
zip all.zip *.jpg
q条命o(h)是将所?jpg的文件压~成一个zip?/p>
q条命o(h)是将all.zip中的所有文件解压出?
要在linux下处?rar文gQ需要安装RAR for LinuxQ可以从|上下蝲Q但要记住,RAR
for Linux
不是免费的;然后安装Q?br />
# tar -xzpvf rarlinux-3.2.0.tar.gz
#
cd rar
# make
q样安装好了,安装后就有了rar和unrarq两个程序,rar是压~程序,unrar是解压程
序。它们的参数选项很多Q这里只做简单介l,依旧举例说明一下其用法Q?br />
# rar a all *.jpg
q条命o(h)是将所
?jpg的文件压~成一个rar包,名ؓ(f)all.rarQ该E序?x)?rar 扩展名将自动附加到包名后?br />
# unrar e
all.rar
q条命o(h)是将all.rar中的所有文件解压出?br />
到此Q我们已l介l过linux下的tar、gzip?
gunzip、bzip2、bunzip2、compress、uncompress、zip、unzip、rar、unrar{程式,你应该已l能够
用它们对.tar?gz?tar.gz?tgz?bz2?tar.bz2?Z?tar.Z?zip?rarq?0U压~文件进行解?
了,以后应该不需要ؓ(f)下蝲了一个Y件而不知道如何在Linux下解开而烦(ch)g。而且以上Ҏ(gu)对于Unix也基本有效?br />
本文介绍了linux?
的压~程式tar、gzip、gunzip、bzip2、bunzip2、compress、uncompress、zip、unzip、rar?
unrar{程式,以及(qing)如何使用它们
?tar?gz?tar.gz?tgz?bz2?tar.bz2?Z?tar.Z?zip?rarq?0U压~文件进行操作?/p>
2. exec(String command,
String envp[], File dir)
3. exec(String cmd, String envp[])
4.
exec(String cmdarray[])
5. exec(String cmdarray[], String envp[])
6. exec(String cmdarray[], String envp[], File dir)
一般的应用E序可以直接使用W一版本Q当有环境变量传递的时候用后面的版本。其??版本可以?
递一个目录,标识当前目录Q因为有些程序是使用相对目录的,所以就要用这个版本?br />
cmd.exe /c start <FileName>
使用DOS命o(h)(比如dir)时也要用到?
用。如果想与调用的E序q行交互Q那么就要用该Ҏ(gu)的返回对象Process了,通过Process?
getInputStream()QgetOutputStream()和getErrorStream()Ҏ(gu)可以得到输入输出,然后通过
InputStream可以得到E序Ҏ(gu)制台的输Z息,通过OutputStream可以l程序输入指?q样pCE序的交换功能?/font>
用Java~写应用Ӟ有时需要在E序中调用另一个现成的可执行程序或pȝ命o(h)Q? q时可以通过l合使用Java提供的RuntimecdProcesscȝҎ(gu)实现。下面是一U比较典型的E序模式Q?/font>
Z优化Java的Lock机制Q从Java6开始引入了轻量U锁的概c(din)?/p>
轻量U锁QLightweight LockingQ本意是Z减少多线E进入互斥的几率Qƈ不是要替代互斥?br /> 它利用了CPU原语Compare-And-Swap(CASQ汇~指令CMPXCHG)Q尝试在q入互斥前,q行补救?/p>
本文详l介lJVM如何利用CASQ实现轻量锁?/p>
Java Object Model中定义,Object Header是一?字(1 word = 4 byteQ长度的存储区域?br /> W一个字长度的区域用来标记同步,GC以及(qing)hash code{,官方UC?mark word。第二个字长度的区域是指向到对象的Class?/p>
?个word中,mark word是轻量锁实现的关键。它的结构见下表
从表中可以看刎ͼstate为lightweight locked的那行即量锁标记。bitfieds名ؓ(f)指向lock record的指针,q里?strong>lock recordQ其实是一块分配在U程堆栈上的I间区域?br /> 用于CAS前,拯object上的mark word(Z么要拯Q请看下??br /> W三Ҏ(gu)重量U锁标记。后面的状态单词很有趣QinflatedQ译胀Q在q里意思其实是锁已升到OS-level?br /> 在本文的范围内,我们只关注第二和W三即可?/p>
Z能直观的理解lockQunlock与mark word之间的联p,我画了一张流E图Q?/p>
在图中,提到了拷贝object mark wordQ由于脱M原始mark wordQ官方将它冠以displaced前缀Q即displaced mark word(|换标记??br /> q个displaced mark word是整个轻量锁实现的关键Q在CAS中的compare需要用它作为条件?/p>
Z么要拯mark wordQ?br /> 其实很简单,原因是ؓ(f)了不惛_lock与unlockq种底层操作上再加同步?/p>
在拷贝完object mark word之后QJVM做了一?strong>交换指针的操?/strong>Q即程中第一个橙色矩形框内容所q?br /> object mark word里的轻量U锁指针指向lock record所在的stack指针Q作用是让其他线E知道,该object monitor已被占用?br /> lock record里的owner指针指向object mark word的作用是Z在接下里的运行过E中Q识别哪个对象被锁住了?/p>
下图直观地描qC交换指针的操作?/p>
最后一步unlock中,我们发现QJVM同样使用了CAS来验证object mark word在持有锁到释N之间Q有无被其他U程讉K?br /> 如果其他U程在持有锁q段旉里,试获取q锁Q则可能自n被挂P而mark word的重量锁指针也?x)被相应修改?br /> 此时Qunlock后就需要唤醒被挂v的线E?/p>
原文链接Q?a rel="bookmark">http://kenwublog.com/theory-of-lightweight-locking-upon-cas
不同q_间的处理器架构将直接影响内存模型的结?
在C或C++? 可以利用不同操作q_下的内存模型来编写ƈ发程? 但是, q带l开发h员的? 更高的学?fn)成?
相比之下, java利用了自w虚拟机的优? 使内存模型不束缚(x)于具体的处理器架? 真正实现了跨q_.
(针对hotspot jvm, jrockit{不同的jvm, 内存模型也会(x)不相?
内存模型的特?
a, Visibility 可视?(多核,多线E间数据的共?
b, Ordering 有序?(对内存进行的操作应该是有序的)
java 内存模型 ( java memory model )
Ҏ(gu)Java Language Specification中的说明, jvmpȝ中存在一个主内存(Main Memory或Java Heap Memory)QJava中所有变量都储存在主存中Q对于所有线E都是共享的?/p>
每条U程都有自己的工作内?Working Memory)Q工作内存中保存的是d中某些变量的拯Q线E对所有变量的操作都是在工作内存中q行Q线E之间无法相互直接访问,变量传递均需要通过d完成?br />
其中, 工作内存里的变量, 在多核处理器? 大部分储存于处理器高速缓存中, 高速缓存在不经q内存时, 也是不可见的.
jmm怎么体现 可视?Visibility) ?
在jmm? 通过q发U程修改变量? 必须线E变量同步回d? 其他U程才能讉K?
jmm怎么体现 有序?Ordering) ?
通过java提供的同步机制或volatile关键? 来保证内存的讉K序.
~存一致性(cache coherencyQ?
什么是~存一致?
它是一U管理多处理器系l的高速缓存区l构Q其可以保证数据在高速缓存区到内存的传输中不?x)丢失或重复?来自wikipedia)
举例理解:
假如有一个处理器有一个更C的变量g于其~存中,但还没有被写入主内存Q这样别的处理器可能会(x)看不到这个更新的?
解决~存一致性的Ҏ(gu)?
a, 序一致性模?
要求某处理器Ҏ(gu)改变的变量值立卌行传? q确保该D所有处理器接受? 才能l箋执行其他指o(h).
b, 释放一致性模? (cMjmm cache coherency)
允许处理器将改变的变量值gq到释放锁时才进行传?
jmm~存一致性模?– “happens-before ordering(先行发生排序)”
一般情况下的示例程?
x = 0;
y = 0;
i = 0;
j = 0;
// thread A
y = 1;
x = 1;
// thread B
i = x;
j = y;
在如上程序中, 如果U程A,B在无保障情况下运? 那么i,j各会(x)是什么值呢?
{案? 不确? (00,01,10,11都有可能出现)
q里没有使用java同步机制, 所?jmm 有序性和可视?都无法得C?
happens-before ordering( 先行发生排序) 如何避免q种情况?
排序原则已经做到:
a, 在程序顺序中, U程中的每一个操? 发生在当前操作后面将要出现的每一个操作之?
b, 对象监视器的解锁发生在等待获取对象锁的线E之?
c, 对volitile关键字修饰的变量写入操作, 发生在对该变量的d之前.
d, 对一个线E的 Thread.start() 调用 发生在启动的U程中的所有操作之?
e, U程中的所有操?发生在从q个U程?Thread.join()成功q回的所有其他线E之?
Z实现 happends-before ordering原则, java?qing)jdk提供的工?
a, synchronized关键?br />
b, volatile关键?br />
c, final变量
d, java.util.concurrent.locks?since jdk 1.5)
e, java.util.concurrent.atmoic?since jdk 1.5)
…
使用了happens-before ordering的例?
(1) 获取对象监视器的?lock)
(2) 清空工作内存数据, 从主存复制变量到当前工作内存, 卛_步数?(read and load)
(3) 执行代码Q改变共享变量?(use and assign)
(4) 工作内存数据刷回主?(store and write)
(5) 释放对象监视器的?(unlock)
注意: 其中4,5两步是同时进行的.
q边最核心的就是第二步, 他同步了d?卛_一个线E对变量改动的结?可以被当前线E获?(利用了happens-before ordering原则)
Ҏ(gu)之前的例?/strong> l典j2ee设计模式Double-Checked Locking失效问题 要展CDCL失效问题, 首先要理解一个重要概? 延迟加蝲(lazy loading). 非单例的单线Egq加载示? 非单例的 多线Egq加载示? 非单例的 DCL多线Egq加载示? Double-Checked Locking看v来是非常完美的。但是很遗憾Q根据Java的语a规范Q上面的代码是不可靠的?/p>
出现上述问题, 最重要?个原因如? 问题出现的顺? 不过, 一些著名的开源框? 包括jive,lenya{也都在使用DCL模式, 且未见一些极端异? DCL的替?Initialize-On-Demand : l基癄的DCL解释: http://en.wikipedia.org/wiki/Double-checked_locking DCL的完解x? http://www.theserverside.com/patterns/thread.tss?thread_id=39606 ȝ: 原文链接Q?a rel="bookmark">http://kenwublog.com/explain-java-memory-model-in-detail
如果多个U程同时执行一D|l锁保护的代码段Q很有可能某条线E已l改动了变量的|但是其他U程却无法看到这个改动,依然在旧的变量gq行q算Q最l导致不可预料的q算l果?/p>
双重(g)查锁定失效问?一直是JMM无法避免的缺陷之一.了解DCL失效问题, 可以帮助我们深入JMMq行原理.class Foo
{
private Resource res = null;
public Resource getResource()
{
// 普通的延迟加蝲
if (res == null)
res = new Resource();
return res;
}
}Class Foo
{
Private Resource res = null;
Public synchronized Resource getResource()
{
// 获取实例操作使用同步方式, 性能不高
If (res == null) res = new Resource();
return res;
}
}Class Foo
{
Private Resource res = null;
Public Resource getResource()
{
If (res == null)
{
//只有在第一ơ初始化?才用同步方?
synchronized(this)
{
if(res == null)
{
res = new Resource();
}
}
}
return res;
}
}
1, ~译器优化了E序指o(h), 以加快cpu处理速度.
2, 多核cpu动态调整指令顺? 以加快ƈ行运能?
1, U程A, 发现对象未实例化, 准备开始实例化
2, ׃~译器优化了E序指o(h), 允许对象在构造函数未调用完前, ?׃n变量的引用指?部分构造的对象, 虽然对象未完全实例化, 但已l不为null?
3, U程B, 发现部分构造的对象已不是null, 则直接返回了该对?
说明, DCL失效问题的出现率q是比较低的.
接下来就是性能与稳定之间的选择?public class Foo {
// 似有静态内部类, 只有当有引用? 该类才会(x)被装?/span>
private static class LazyFoo {
public static Foo foo = new Foo();
}
public static Foo getInstance() {
return LazyFoo.foo;
}
}
多线E编E? 针对有写操作的变? 必须 保证其所有引用点与主存中数据一?考虑采用同步或volatile) .
]]>
Z?使用volatile比同步代h?
同步的代? 主要由其覆盖范围军_, 如果可以降低同步的覆盖范? 则可以大q提升程序性能.
而volatile的覆盖范围仅仅变量别的. 因此它的同步代h(hun)很低.
volatile原理是什?
volatile的语? 其实是告诉处理器, 不要我攑օ工作内存, L(fng)接在d操作?(工作内存详见java内存模型)
因此, 当多核或多线E在讉K该变量时, 都将直接 操作 d, q从本质? 做到了变量共?
volatile的有什么优?
1, 更大的程序吞吐量
2, 更少的代码实现多U程
3, E序的~性较?br />
4, 比较好理? 无需太高的学?fn)成?/p>
volatile有什么劣?
1, Ҏ(gu)出问?br />
2, 比较难设?br />
volatileq算存在脏数据问?
volatile仅仅能保证变量可见? 无法保证原子?
volatile的race conditionCZ:
public class TestRaceCondition {
private volatile int i = 0;
public void increase() {
i++;
}
public int getValue() {
return i;
}
}
当多U程执行increaseҎ(gu)? 是否能保证它的g(x)是线性递增的呢?
{案是否定的.
原因:
q里的increaseҎ(gu), 执行的操作是i++, ?i = i + 1;
针对i = i + 1, 在多U程中的q算, 本n需要改变i的?
如果, 在i已从内存中取到最新? 但未?q行q算, 此时其他U程已数ơ将q算l果赋值给i.
则当前线E结束时, 之前的数ơ运结果都被覆盖.
? 执行100ơincrease, 可能l果?< 100.
一般来? q种情况需要较高的压力与ƈ发情况下, 才会(x)出现.
如何避免q种情况?
解决以上问题的方?
一U是 操作? 加上同步.
q种Ҏ(gu), 无疑大大降低程序性能, 且违背了volatile的初?
W二U方式是, 使用g原语(CAS), 实现非阻塞算?br /> 从CPU原语? 支持变量U别的低开销同步.
CPU原语-比较q交?CompareAndSet),实现非阻塞算?
什么是CAS?
cas是现代CPU提供lƈ发程序用的原语操作. 不同的CPU有不同的使用规范.
?Intel 处理器中Q比较ƈ交换通过指o(h)?cmpxchg pd实现?br />
PowerPC 处理器有一对名?#8220;加蝲q保?#8221;?#8220;条g存储”的指令,它们实现相同的目圎ͼ
MIPS ?PowerPC 处理器相|除了W一个指令称?#8220;加蝲链接”?/p>
CAS 操作包含三个操作?—?内存位置QVQ、预期原|AQ和新?B)
什么是非阻塞算?
一个线E的p|或挂起不应该影响其他U程的失败或挂v.q类法UC为非d(nonblocking)法
Ҏ(gu)d法:
如果有一cdƈ发操? 其中一个线E优先得到对象监视器的锁, 当其他线E到辑步边界时, ׃(x)被阻?
直到前一个线E释放掉锁后, 才可以l竞争对象锁.(当然,q里的竞争也可是公^? 按先来后到的ơ序)
CAS 原理:
我认Z|?V 应该包含?AQ如果包含该|则将 B 攑ֈq个位置Q否则,不要更改该位|,只告诉我q个位置现在的值即可?/p>
CAS使用CZ(jdk 1.5 q发?AtomicIntegercd?)
/**
* Atomically sets to the given value and returns the old value.
*
* @param newValue the new value
* @return the previous value
*/
public final int getAndSet(int newValue) {
for (;;) {
int current = get();
if (compareAndSet(current, newValue))
return current;
}
}
public final boolean compareAndSet(int expect, int update) {
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
}
q个Ҏ(gu)? AtomicIntegercȝ常用Ҏ(gu), 作用? 变量设|ؓ(f)指定? q返回设|前的?
它利用了cpu原语compareAndSet来保障值的唯一?
? AtomicIntegercM, 其他的实用方? 也是Z同样的实现方?
比如 getAndIncrement, getAndDecrement, getAndAdd{等.
CAS语义上存在的 ” ABA 问题”
什么是ABA问题?
假设, W一ơ读取V地址的A? 然后通过CAS来判断V地址的值是否仍旧ؓ(f)A, 如果? 将B的值写入V地址,覆盖A?
但是, 语义? 有一个漏z? 当第一ơ读取V的A? 此时, 内存V的值变为B? 然后在未执行CAS? 又变回了A?
此时, CAS再执行时, ?x)判断其正确? q进行赋?
q种判断值的方式来断定内存是否被修改q? 针对某些问题, 是不适用?
Z解决q种问题, jdk 1.5q发包提供了AtomicStampedReference(有标记的原子引用)c? 通过控制变量值的版本来保证CAS正确?
其实, 大部分通过值的变化来CAS, 已经够用?
jdk1.5原子包介l?Zvolatile)
包的特色:
1, 普通原子数值类型AtomicInteger, AtomicLong提供一些原子操作的加减q算.
2, 使用了解册数据问题的经典模?”比对后设?#8221;, ?查看d中数据是否与预期提供的g?如果一?才更?
3, 使用AtomicReference可以实现Ҏ(gu)有对象的原子引用?qing)赋?包括Double与Float,
但不包括对其的计?点的计?只能依靠同步关键字或Lock接口来实C.
4, Ҏ(gu)l元素里的对?W合以上特点? 也可采用原子操作.包里提供了一些数l原子操作类
AtomicIntegerArray, AtomicLongArray{等.
5, 大幅度提升系l吞吐量?qing)性能.
具体使用, 详解java doc.
原文链接Q?a rel="bookmark">http://kenwublog.com/the-theory-of-volatile