Archive

Archive for the ‘$Programming’ Category

细节背后:为什么线程协作之前必须先获得锁?

October 3rd, 2009 西坪 No comments

为什么Object.wait()/notify()/notifyAll() 之前必须获得锁? 这是JLS的规定。Wait-notify机制是围绕监控器锁进行的,获得锁是很自然的前提,自身没有拿到锁之前,怎么能够尝试去操作靠锁来调控的线程呢?不过今天偶尔有时间,就看下Sun Hotspot是怎么实现这一机制的。

当我们执行下面的代码时,线程会抛出异常java.lang.IllegalMonitorStateException: current thread not owner。

public class WaitNotifyCompilerCode {
	private String aString = "Hello World!";
 
	public static void main(String[] args) {
		System.out.println("Execute start ....");
		final WaitNotifyCompilerCode w = new WaitNotifyCompilerCode();
		w.wait1SecAndPrintString();
		System.out.println("Execute end ....");
	}
 
	public void wait1SecAndPrintString() {
		try {
			this.wait(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(aString);
	}
 
}

异常栈的信息如下:

Exception in thread "main" java.lang.IllegalMonitorStateException: current thread not owner
	at java.lang.Object.wait(Native Method)
	at com.feihoo.test.waitnotify.WaitNotifyCompilerCode.wait1SecAndPrintString(WaitNotifyCompilerCode.java:35)
	at com.feihoo.test.waitnotify.WaitNotifyCompilerCode.main(WaitNotifyCompilerCode.java:27)

深入查看 OpenJDK的源码,找到 Object.wait() 函数本地代码:

JVM_ENTRY(void, JVM_MonitorWait(JNIEnv* env, jobject handle, jlong ms))
  JVMWrapper("JVM_MonitorWait");
  Handle obj(THREAD, JNIHandles::resolve_non_null(handle));
  assert(obj->is_instance() || obj->is_array(), "JVM_MonitorWait must apply to an object");
  JavaThreadInObjectWaitState jtiows(thread, ms != 0);
  if (JvmtiExport::should_post_monitor_wait()) {
    JvmtiExport::post_monitor_wait((JavaThread *)THREAD, (oop)obj(), ms);
  }
  ObjectSynchronizer::wait(obj, ms, CHECK);
JVM_END

重点看倒数第二行,调用的函数如下面的代码:

// NOTE: must use heavy weight monitor to handle wait()
void ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) {
  if (UseBiasedLocking) {
    BiasedLocking::revoke_and_rebias(obj, false, THREAD);
    assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now");
  }
  if (millis < 0) {
    TEVENT (wait - throw IAX) ;
    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "timeout value is negative");
  }
  ObjectMonitor* monitor = ObjectSynchronizer::inflate(THREAD, obj());
  DTRACE_MONITOR_WAIT_PROBE(monitor, obj(), THREAD, millis);
  monitor->wait(millis, true, THREAD);

而上面的代码中最后一行的函数里,在做实际操作之前调用了下面的宏:

// A macro is used below because there may already be a pending
// exception which should not abort the execution of the routines
// which use this (which is why we don't put this into check_slow and
// call it with a CHECK argument).
 
#define CHECK_OWNER()                                                             \
  do {                                                                            \
    if (THREAD != _owner) {                                                       \
      if (THREAD->is_lock_owned((address) _owner)) {                              \
        _owner = THREAD ;  /* Convert from basiclock addr to Thread addr */       \
        _recursions = 0;                                                          \
        OwnerIsThread = 1 ;                                                       \
      } else {                                                                    \
        TEVENT (Throw IMSX) ;                                                     \
        THROW(vmSymbols::java_lang_IllegalMonitorStateException());               \
      }                                                                           \
    }                                                                             \
  } while (false)
Categories: $Programming Tags: , ,

Flex中的对象比较(相等性)

January 5th, 2009 西坪 No comments

Flex中的对象相等性是什么样的呢?国外有篇文章讨论了这一问题:Architectural Atrocities, part 8: is there no equality?

下面是我从Flex的参考手册中找出来的一些东西。

Equality operators

The equality operators take two operands, compare their values, and return a Boolean value. All the equality operators, as listed in the following table, have equal precedence:

Operator Operation performed
== Equality
!= Inequality
=== Strict equality
!== Strict inequality

IUID

Package mx.core
Interface public interface IUID

The IUID interface defines the interface for objects that must have Unique Identifiers (UIDs) to uniquely identify the object. UIDs do not need to be universally unique for most uses in Flex. One exception is for messages send by data services.


Data providers and the uid property

Flex data provider controls use a unique identifier (UID) to track data items. Flex can automatically create and manage UIDs. However, there are circumstances when you must supply your own uid property by implementing the IUID interface, and there are circumstances when supplying your own uid property improves processing efficiency.

Because the Object and Array classes are dynamic, you normally do not do anything special for data objects whose items belong to these classes. However, you should consider implementing the IUID if your data object items belong to custom classes that you define.

Note: When Flex creates a UID for an object, such as an item in an ArrayCollection, it adds the UID as an mx_internal_uid property of the item. Flex creates mx_internal_uid properties for any objects that are dynamic and do not have bindable properties. To avoid having Flex create mx_internal_uid properties, the object class should do any of the following things: have at least one property with a [Bindable] metadata tag; implement the IUID interface; or have a uid property with a value.

If Flex must consider two or more different objects to be identical, the objects must implement the IUID interface so that you can assign the same uid value to multiple objects. A typical case where you must implement the IUID interface is an application that uses paged collections. As the cursor moves through the collection, a particular item might be pulled down from the server and released from memory repeatedly. Every time the item is pulled into memory, a new object is created to represent the item. If you need to compare items for equality, Flex should consider all objects that represent the same item to be the same “thing.”

More common than the case where you must implement the IUID interface is the case where you can improve processing efficiency by doing so. As a general rule, you do not implement the IUID interface if the data provider elements are members of dynamic classes. Flex can automatically create a uid property for these classes. There is still some inefficiency, however, so you might consider implementing the IUID interface if processing efficiency is particularly important.

In all other cases, Flex uses the Dictionary mechanism to manage the uid, which might not be as efficient as supplying your own UID.

Categories: $Programming Tags:

有关 sum与limit组合使用时的问题

June 25th, 2008 西坪 No comments

select sum(a) from test_table order by b desc limit 1,2

这个句子,在MySQL 和 Sqlite3下,如此 sum得到的是 Empty Set

而 select sum(a) from test_table order by b desc limit 0,2 则返回全部记录的a字段的合计,limit不起作用。

但是去掉sum函数的话, select a from test_table order by b desc limit 1,2 能够选择出需要的行。

为什么? 来自 MySQL 官方站点论坛的解释:

The LIMIT clause affects only the number of rows returned, and this query in fact only returns one row. You might want to try something like this:

SELECT sum(quantity)
FROM (SELECT quantity
FROM stock_card
LIMIT 0,2
) AS subquery;

Categories: $Programming Tags: