修改cas协议 https协议 改成http

写道
凉鞋与拖鞋的约会
edu.yale.its.tp.cas.util.SecureURL的 public static String retrieve(String url) throws IOException 类地换成
public static String retrieve(String url) throws IOException {
BufferedReader r = null;

try {
URL u = new URL(url);
URLConnection uc = u.openConnection();
uc.setRequestProperty("Connection", "close");
r = new BufferedReader(new InputStreamReader(uc.getInputStream()));
String line;
StringBuffer buf = new StringBuffer();
while ((line = r.readLine()) != null)
buf.append(line + "\n");
return buf.toString();
} finally {
try {
if (r != null)
r.close();
} catch (IOException ex) {
// ignore
}
}
}


[b]edu.yale.its.tp.cas.client.Uitil类
的public static String getService(HttpServletRequest request, String server)
throws ServletException
修改为[/b]

public static String getService(HttpServletRequest request, String server)
throws ServletException {
if (log.isTraceEnabled()){
log.trace("entering getService(" + request + ", " + server + ")");
}

// ensure we have a server name
if (server == null) {
log.error("getService() argument \"server\" was illegally null.");
throw new IllegalArgumentException("name of server is required");
}


// now, construct our best guess at the string
StringBuffer sb = new StringBuffer();
if (request.isSecure())
sb.append("https://");
else
sb.append("http://");
sb.append(server);
sb.append(request.getRequestURI());

if (request.getQueryString() != null&&!"".equals(request.getQueryString())) {
// first, see whether we've got a 'ticket' at all
int ticketLoc = request.getQueryString().indexOf("ticket=");

// if ticketLoc == 0, then it's the only parameter and we ignore
// the whole query string

// if no ticket is present, we use the query string wholesale
if (ticketLoc == -1)
sb.append("?" + request.getQueryString());
else if (ticketLoc > 0) {
ticketLoc = request.getQueryString().indexOf("&ticket=");
if (ticketLoc == -1) {
// there was a 'ticket=' unrelated to a parameter named 'ticket'
sb.append("?" + request.getQueryString());
} else if (ticketLoc > 0) {
// otherwise, we use the query string up to "&ticket="
sb.append("?" + request.getQueryString().substring(0, ticketLoc));
}
}
}
String encodedService = URLEncoder.encode(sb.toString());
if (log.isTraceEnabled()){
log.trace("returning from getService() with encoded service [" + encodedService + "]");
}
return encodedService;
}

[url=http://tms.taoke.alimama.com/tms/topic.php?pid=mm_11452884_0_0&eventid=100806" target="_blank"]凉鞋与拖鞋的约会[/url]
<think>嗯,我现在要理解CAS(比较并交换)在Java中的AtomicInteger类是如何保证原子性的。用户提供的代码里,两个线程各自对AtomicInteger进行1000次自增,理论上最终结果应该是2000。但用户的问题是,compareAndSet方法底层如何保证原子性,尤其是在比较和修改期间,如果有其他线程修改了值,会不会导致同步问题。 首先,CAS的原理是“先比较再交换”。在代码中,每个线程进入循环,先获取当前值expected,然后计算新值newVal,接着调用compareAndSet(expected, newVal)。如果此时value的当前值还是expected,那么就会成功设置为newVal,否则循环重试。 用户的问题核心在于,如果在比较的时候值是100,但在尝试设置的时候,另一个线程已经改成了101,这时候会发生什么?是否在比较和设置的过程中,其他线程无法访问value,从而保证原子性? 根据我之前的了解,CAS操作在底层是通过硬件指令实现的,比如在x86架构中的CMPXCHG指令。这个指令会检查某个内存位置的值是否与预期值相同,如果相同,则更新为新值。整个过程是一个原子操作,即在这个过程中,处理器会确保该操作不可被中断,其他线程无法干扰。因此,当compareAndSet执行时,从读取当前值到比较并交换的整个过程是原子的,不会被其他线程打断。 那用户提到的,如果在比较阶段读取到100,而另一个线程在此时修改为101的情况,这时候compareAndSet会发现当前值已经不是expected的100了,所以会返回false,导致循环继续,重新读取当前值,再次尝试。因此,即使有并发修改CAS机制通过不断重试来确保最终的正确性,而不会出现覆盖的情况。 不过,用户可能还有疑问,比如这个原子性是如何在硬件层面实现的。可能需要进一步解释,处理器如何锁定总线或者使用缓存行锁定来确保原子性。例如,当执行CMPXCHG指令时,处理器会锁定内存总线,防止其他核心或线程访问同一内存地址,直到指令完成。或者,现代处理器可能使用缓存锁定机制,在缓存级别实现原子操作,避免锁定整个总线带来的性能问题。 另外,AtomicInteger中的value变量是用volatile修饰的,保证了可见性,即一个线程修改后,其他线程能立即看到最新的值。因此,在循环中每次读取expected的时候,都能获取到最新的值,而不会使用陈旧的缓存值。 总结一下,CAS通过硬件支持的原子指令,在单个指令周期内完成比较和交换操作,确保这两个步骤的原子性,从而避免了多线程竞争的问题。而当检测到值被其他线程修改时,当前线程会通过自旋重试,直到成功更新为止。这样既保证了线程安全,又避免了使用锁带来的性能开销。</think>CAS(Compare-And-Swap)的原子性保障是通过**硬件指令**实现的。以下分步骤解释其底层原理和代码行为: --- ### **1. CAS操作的本质** CAS操作包含三个核心步骤: 1. **读取当前值** 2. **比较当前值与预期值** 3. **若匹配,则写入新值** **关键点**:这三个步骤在底层被合并为**一条原子指令**(如x86的`CMPXCHG`指令),确保操作不可分割。 --- ### **2. 硬件级别的原子性** - **硬件指令支持**: CPU提供原子指令(如`CMPXCHG`),直接操作内存地址。执行期间: - 锁定缓存行(缓存一致性协议,如MESI)或总线(旧处理器),阻止其他CPU核心访问同一内存地址。 - 比较和写入在单个指令周期内完成,**外界无法打断**。 - **示例流程**: ```plaintext Thread1: 读取value=100 → 准备写入101 Thread2: 尝试写入101前,Thread2已写入101 → CAS失败 → Thread1重试 ``` --- ### **3. Java层的实现** - **AtomicInteger的compareAndSet方法**: 调用`Unsafe`类的`compareAndSwapInt`方法,直接映射到上述硬件指令。 ```java public final boolean compareAndSet(int expectedValue, int newValue) { return unsafe.compareAndSwapInt(this, valueOffset, expectedValue, newValue); } ``` - **内存屏障与可见性**: `value`字段用`volatile`修饰,保证: 1. 线程每次读取的是最新值。 2. 写入后立即刷新到主内存,其他线程可见。 --- ### **4. 代码行为分析** - **当竞争发生时**: 若某线程的`expected=100`,但执行CAS前value已被其他线程改为101: - **CAS失败**,返回`false`,循环继续。 - **重新读取最新值**,计算新值,再次尝试。 - 最终所有线程的自增操作会通过重试完成。 - **无锁但非阻塞**: 线程不会挂起(如锁机制),而是通过**自旋重试**(即代码中的`do-while`循环)实现同步。 --- ### **5. 为何结果正确?** - **线性化保证**: 每次CAS成功意味着当前线程是唯一修改者。 - **最终一致性**: 即使多线程竞争,所有自增操作最终会被重试成功,总和必为2000。 --- ### **6. 对比锁机制** | | CAS(无锁) | 锁(如synchronized) | |----------|------------------|---------------------| | **竞争处理** | 自旋重试 | 线程挂起等待 | | **吞吐量** | 高(无上下文切换) | 低 | | **适用场景** | 低竞争、短耗时操作 | 高竞争、长耗时操作 | --- ### **总结** - **原子性**:由硬件指令保证比较和写入的不可分割性。 - **可见性**:`volatile`确保值修改的实时可见。 - **最终正确性**:通过自旋重试覆盖所有可能的竞争条件。 你的代码能正确输出2000,正是因为CAS的原子性和重试机制共同作用。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值