文獻翻譯:Java theory and practice: Fixing the Java Memory Model, Part 2

Java theory and practice: Fixing the Java Memory Model, Part 2

譯:Java 理論與實踐:修復 Java 內存模型,第 2 部分

翻譯自:http://www.ibm.com/developerworks/library/j-jtp03304/(原文寫于2004年3月,經典永不過時)

JSR 133, which has been active for nearly three years, has recently issued its public recommendation on what to do about the Java Memory Model (JMM). In Part 1 of this series, columnist Brian Goetz focused on some of the serious flaws that were found in the original JMM, which resulted in some surprisingly difficult semantics for concepts that were supposed to be simple. This month, he reveals how the semantics of volatile and final will change under the new JMM, changes that will bring their semantics in line with most developers’ intuition. Some of these changes are already present in JDK 1.4; others will have to wait until JDK 1.5.

譯:JSR133 規范,已經活躍將近 3 年了,最近發布了關于要對 JMM 做哪些事情的建議。在本系列的 Part1 部分,專欄作家 Brian Goetz 詳細的介紹了原來的 JMM 中被發現的一些致命的缺陷,這些缺陷導致了一些本來應該很簡單的概念卻有了難以理解的語法含義。這個月(2004-03)他展示了在新的 JMM 中,關鍵字 volatilefinal 的語義將會如何改變,而這些改變會使這兩個關鍵字的語義符合大多數開發者的理解。

Writing concurrent code is hard to begin with; the language should not make it any harder. While the Java platform included support for threading from the outset, including a cross-platform memory model that was intended to provide “Write Once, Run Anywhere” guarantees for properly synchronized programs, the original memory model had some holes. And while many Java platforms provided stronger guarantees than were required by the JMM, the holes in the JMM undermined the ability to easily write concurrent Java programs that could run on any platform. So in May of 2001, JSR 133 was formed, charged with fixing the Java Memory Model. Last month, I talked about some of those holes; this month, I’ll talk about how they’ve been plugged.

譯:寫并發的代碼本身已經十分困難了,因此語言不應該讓它變的更難。盡管 Java 平臺在設計之初就引入了對線程的支持,包括通過提供一個 “書與一次,到處運行” 的跨平臺的內存模型來保證程序的同步,但是原始的內存模型還是存在一些漏洞。盡管許多的 Java 平臺提供了比 JMM 要求的更加嚴格的保證,但 JMM 中的這些漏洞仍然使寫并發的 JAVA 代碼變得并不不容易。因此,在2001年5月,為了修復 JMM 中的這些漏洞,JSR133 規范被制定了。上個月,我談論了這些漏洞。這個月,我要聊聊漏洞是如何被修復的。

Visibility, revisited(再探 可見性)

One of the key concepts needed to understand the JMM is that of visibility – how do you know that if thread A executes someVariable = 3, other threads will see the value 3 written there by thread A? A number of reasons exist for why another thread might not immediately see the value 3 forsomeVariable: it could be because the compiler has reordered instructions in order to execute more efficiently, or that someVariable was cached in a register, or that its value was written to the cache on the writing processor but not yet flushed to main memory, or that there is an old (or stale) value in the reading processor’s cache. It is the memory model that determines when a thread can reliably “see” writes to variables made by other threads. In particular, the memory model defines semantics for volatile, synchronized, and final that make guarantees of visibility of memory operations across threads.

譯:JMM中 一個重要的概念,即可見性(visibility)—— 你怎樣才能知道如果 線程A 執行了 someVariable=3,其他的線程能夠看到被 線程A 寫入的那個值 3?其他的線程無法立刻看到 someVariable 變量的值為 3 的原因有很多:可能是編譯器為了代碼的運行效率進行了指令的重排序,或者是 someVariable 被緩存在了 CPU 的寄存器中,或者是someVariable 被放到了寫處理器的緩存中還沒來得及刷新到主內存,又或者是讀處理器的緩存中有一個舊值。內存模型決定了一個線程何時可以可靠的看到被其他線程寫入的值,而且,內存模型定義了 volatile, finalsynchronized 等關鍵字的語義,而這些保證了多線程操作內存時的可見性。

When a thread exits a synchronized block as part of releasing the associated monitor, the JMM requires that the local processor cache be flushed to main memory. (Actually, the memory model does not talk about caches – it talks about an abstraction, local memory, which encompasses caches, registers, and other hardware and compiler optimizations.) Similarly, as part of acquiring the monitor when entering a synchronized block, local caches are invalidated so that subsequent reads will go directly to main memory and not the local cache. This process guarantees that when a variable is written by one thread during a synchronized block protected by a given monitor and read by another thread during a synchronized block protected by the same monitor, the write to the variable will be visible by the reading thread. The JMM does not make this guarantee in the absence of synchronization – which is why synchronization (or its younger sibling, volatile) must be used whenever multiple threads are accessing the same variables.

譯:作為釋放監視器的一部分(Java中每個對象都有且僅有一個關聯的監視器),當一個線程退出同步代碼塊時,JMM 將要求處理器緩存中的內容必須刷新到主內存。與之同理,作為獲取監視器的一部分,當一個線程進入同步代碼塊的時候,JMM 則會要求失效本地緩存中的內容,以便之后的讀操作會直接訪問主內存而不是本地緩存。這樣的過程就保證了,當一個線程在被監視器保護的同步代碼塊中寫入變量,而另一個線程在被同一個監視器保護的同步代碼塊中讀取變量時,寫操作的結果對于進行讀操作的線程是可見的。JMM 的這個機制只出現在同步存在的場景中,這也是為什么當多線程訪問共享變量時,我們必須使用 sychronized 關鍵字。

New Guarantees for volatile(對于 volatile 的新保證)

The original semantics for volatile guaranteed only that reads and writes of volatile fields would be made directly to main memory, instead of to registers or the local processor cache, and that actions on volatile variables on behalf of a thread are performed in the order that the thread requested. In other words, this means that the old memory model made promises only about the visibility of the variable being read or written, and no promises about the visibility of writes to other variables. While this was easier to implement efficiently, it turned out to be less useful than initially thought.

譯:原來的 volatile 的語義保證了只有對 volatile 成員變量的讀寫操作是直接操作主內存的,而不去操作寄存器或者處理器緩存,并且代表線程對 volatile 變量執行的操作是按照線程請求的順序執行的。換句話說,這意味著舊的內存模型只保證正在被讀寫的變量的可見性,但并不保證寫其他變量的可見性。盡管這樣實現起來很容易,但事實證明這樣實現并沒有什么用處。

While reads and writes of volatile variables could not be reordered with reads and writes of other volatile variables, they could still be reordered with reads and writes of nonvolatile variables. In Part 1, you learned how the code in Listing 1 was not sufficient (under the old memory model) to guarantee that the correct value for configOptions and all the variables reachable indirectly through configOptions (such as the elements of the Map) would be visible to thread B, because the initialization of configOptions could have been reordered with the initialization of the volatileinitialized variable.

譯:盡管對多個 volatil 變量的讀寫操作之間不會進行重排序,但是對 volatile 變量和非 volatile 變量的讀寫操作之間還是會發生重排序的。如下,列舉 1 中的代碼并不足以保證 configOptions(即 Map 元素) 的值和通過 configOptions 間接獲取到的值對于 線程B 是可見的,因為對 configOptions 變量的初始化指令可能會和 initialized 變量的初始化指令重排序。

Listing 1. Using a volatile variable as a “guard”(列舉1. 使用 volatile 變量作為“保證”)
Map configOptions;
char[] configText;
volatile boolean initialized = false;// In Thread A
configOptions = new HashMap();
configText = readConfigFile(fileName);
processConfigOptions(configText, configOptions);
initialized = true;// In Thread B
while (!initialized) sleep();
// use configOptions

Unfortunately, this situation is a common use case for volatile – using a volatile field as a “guard” to indicate that a set of shared variables had been initialized. The JSR 133 Expert Group decided that it would be more sensible for volatile reads and writes not to be reorderable with any other memory operations – to support precisely this and other similar use cases. Under the new memory model, when thread A writes to a volatile variable V, and thread B reads from V, any variable values that were visible to A at the time that V was written are guaranteed now to be visible to B. The result is a more useful semantics of volatile, at the cost of a somewhat higher performance penalty for accessing volatile fields.

譯:不幸的是,上面的使用場景很常見。即,volatile 變量被當成一個標記以判斷是否所有的變量都被進行了合理的初始化。針對這樣類型的場景,JSR133 規范專家組決定,對 volatile 變量的讀寫操作和對非 volatile 變量的讀寫操作之間禁止發生指令重排序是合理的。在新的內存模型中,如果 線程A 向 volatile 變量V 寫入一個值,線程B 從 變量V 讀取一個值,那么任何 線程A 在寫入 變量V 時可見的值,對于 線程B 都必須保證是可見的。通過這樣的方式,使得 volatile關鍵字 的語義更加的符合使用場景,成本是相比原來訪問 volatile變量 時會有一些性能的降低。

What happens before what?(happens-before 是什么?)

Actions, such as reads and writes of variables, are ordered within a thread according to what is called the “program order” – the order in which the semantics of the program say they should occur. (The compiler is actually free to take some liberties with the program order within a thread as long as as-if-serial semantics are preserved.) Actions in different threads are not necessarily ordered with respect to each other at all – if you start two threads and they each execute without synchronizing on any common monitors or touching any common volatile variables, you can predict exactly nothing about the relative order in which actions in one thread will execute (or become visible to a third thread) with respect to actions in the other thread.

譯:諸如對變量的讀寫操作,它們在線程內會被根據一個叫做 “program order” 的東西進行排序。“program order” 代表程序的代碼語義發生的順序。編譯器實際上在決定線程中的程序順序這件事上是有一些自由的,只要保留了 as-if-serial 語義即可。在不同的線程中,操作執行的順序在彼此之間是不確定的——如果你啟動了兩個線程,并且這兩個線程之間沒有通過共用的監視器進行同步,也沒有操作同一個 volatile 變量的話,那么你對這兩個線程中的各個操作執行時的相對順序是無法進行任何推測的。

Additional ordering guarantees are created when a thread is started, a thread is joined with another thread, a thread acquires or releases a monitor (enters or exits a synchronized block), or a thread accesses a volatile variable. The JMM describes the ordering guarantees that are made when a program uses synchronization or volatile variables to coordinate activities in multiple threads. The new JMM, informally, defines an ordering called happens-before, which is a partial ordering of all actions within a program, as follows:

  • Each action in a thread happens-before every action in that thread that comes later in the program order
  • An unlock on a monitor happens-before every subsequent lock on that same monitor
  • A write to a volatile field happens-before every subsequent read of that same volatile
  • A call to Thread.start() on a thread happens-before any actions in the started thread
  • All actions in a thread happen-before any other thread successfully returns from a Thread.join() on that thread

譯:當一個線程啟動時,額外的順序保證可能被創建,比如當一個線程被 joined 到另一個線程時,一個線程進入或者退出同步塊時,或者一個線程訪問 volatile變量 時。JMM 內存模型描述了當程序使用 synchronized 或者 volatile變量 來協調多個線程之間的行動時所需要進行的保證(也可以說需要遵守的規范)。新的 JMM,定義了一個順序規范,即 happens-before:

  • 一個線程中的每一個操作都要 happens-before 在同一個線程中的之后出現的操作(按照 program order 定義的順序)
  • 在監視器上的解鎖操作要 happens-before 在之后發生的同一個監視器上的加鎖操作
  • 對于 volatile 變量的寫操作要 happens-before 在之后發生的對于同一個 volatile 變量的讀操作
  • 對于一個線程的 Thread.start() 的操作要 happens-before 在該已經啟動的線程上的任何其他操作
  • 一個線程上的所有操作要 happens-before 從當前線程的 Thread.join() 操作成功返回之后的線程上的操作

It is the third of these rules, the one governing reads and writes of volatile variables, that is new and fixes the problem with the example in Listing 1. Because the write of the volatile variable initialized happens after the initialization of configOptions, the use of configOptions happens after the read of initialized, and the read of initialized happens after the write to initialized, you can conclude that the initialization ofconfigOptions by thread A happens before the use of configOptions by thread B. Therefore, configOptions and the variables reachable through it will be visible to thread B.

譯:在上述規則中的第三條,對于 volatile 變量的讀寫操作的規范,修復了上述 Listing 1 中提到的問題。因為對于 configOptions變量的初始化 happens-before 對于 volatile變量 initialized 的寫操作,而對于 initialized變量 的寫操作要 happens-before 對于 initialized 的讀操作,而對于 initialized 的讀操作要 happens-before 對于configOptions變量 的使用,因此保證了對于 configOptions變量 的初始化發生在使用 configOptions 之前。即,configOptions 變量的值對于線程B一定是可見的。

Figure1. Using synchronization to guarantee visibility of memory writes across threads(圖1. 使用同步確保線程間內存寫入的可見性)

Data races(數據競爭)

A program is said to have a data race, and therefore not be a “properly synchronized” program, when there is a variable that is read by more than one thread, written by at least one thread, and the write and the reads are not ordered by a happens-before relationship.

譯:當一個變量被超過一個線程讀取,被至少一個線程寫入,并且讀操作和寫操作無法滿足 happens-before 原則時,我們就說包含這個變量的程序是有數據競爭的(data race),因此這個程序也不是”正確同步”的程序。

Does this fix the double-checked locking problem?(這是否解決了雙重校驗鎖問題?)

One of the proposed fixes to the double-checked locking problem was to make the field that holds the lazily initialized instance a volatile field. (SeeResources for a description of the double-checked locking problem and an an explanation of why the proposed algorithmic fixes don’t work.) Under the old memory model, this did not render double-checked locking thread-safe, because writes to a volatile field could still be reordered with writes to other nonvolatile fields (such as the fields of the newly constructed object), and therefore the volatile instance reference could still hold a reference to an incompletely constructed object.

譯:雙重校驗鎖(DCL)的一個修復方式就是把持有懶初始化實例的那個變量設置為 volatile變量(雙重檢驗鎖問題參考文章[2])。在老的 Java 內存模型中,雙重校驗鎖并不是線程安全的,因為對于volatile變量的寫操作可能會被和非 volatile 變量的寫操作進行重排序。例如,新構造的對象因為指令重排序在初始化完成之前就被賦給了 volatile 變量,因此 volatile 變量實例引用的值可能仍然指向的是一個沒有完成初始化的構造對象。

Under the new memory model, this “fix” to double-checked locking renders the idiom thread-safe. But that still doesn’t mean that you should use this idiom! The whole point of double-checked locking was that it was supposed to be a performance optimization, designed to eliminate synchronization on the common code path, largely because synchronization was relatively expensive in very early JDKs. Not only has uncontended synchronization gotten a lot cheaper since then, but the new changes to the semantics of volatile make it relatively more expensive than the old semantics on some platforms. (Effectively, each read or write to a volatile field is like “half” a synchronization – a read of a volatile has the same memory semantics as a monitor acquire, and a write of a volatile has the same semantics as a monitor release.) So if the goal of double-checked locking is supposed to offer improved performance over a more straightforward synchronized approach, this “fixed” version doesn’t help very much either.

譯:在新的 Java 內存模型中,隨著我們上文論述的一些修復,DCL 的使用是線程安全的了。但這并意味著你應該使用DCL。早期使用DCL的理由是使用它來進行性能優化,使用它來降低在相同代碼塊上進行同步時可能發生的沖突,因為在早期的 Jdk 中,同步是一件昂貴的操作。但現在,非競爭同步已經變得輕量了很多,并且 volatile 的語義的改變使得它在某些舊版本的 Java 平臺上會變得很重量級。(實際上,對于 volatile 變量的每一次讀寫操作都相當于半個 synchronized —— 對于 volatile 變量的讀和獲取監視器的語義是相同的,對于 volatile 變量的寫操作和釋放監視器的語義是相同的)。因此,如果使用雙重校驗鎖的目標是獲取比 synchronized 更好的性能,那么使用改進語義后的 volatile 變量并不會有任何幫助。

Instead of double-checked locking, use the Initialize-on-demand Holder Class idiom, which provides lazy initialization, is thread-safe, and is faster and less confusing than double-checked locking:

譯:代替使用雙重校驗鎖,我們可以使用靜態內部類的方式,這種方式也能提供懶初始化,并且也是線程安全的,并且比雙重校驗鎖更高效也更容易理解。

Listing 2. The Initialize-On-Demand Holder Class idiom(列舉2. Initialize-On-Demand Holder 類習慣用法)
private static class LazySomethingHolder {public static Something something = new Something();
}...public static Something getInstance() {return LazySomethingHolder.something;
}

This idiom derives its thread safety from the fact that operations that are part of class initialization, such as static initializers, are guaranteed to be visible to all threads that use that class, and its lazy initialization from the fact that the inner class is not loaded until some thread references one of its fields or methods.

譯:上述方式是線程安全的,因為類的初始化是線程安全的。上述方式也是懶初始化的,因為內部類一直到被真正使用的時候才會被加載。

Initialization safety(初始化安全)

The new JMM also seeks to provide a new guarantee of initialization safety – that as long as an object is properly constructed (meaning that a reference to the object is not published before the constructor has completed), then all threads will see the values for its final fields that were set in its constructor, regardless of whether or not synchronization is used to pass the reference from one thread to another. Further, any variables that can be reached through a final field of a properly constructed object, such as fields of an object referenced by a final field, are also guaranteed to be visible to other threads as well. This means that if a final field contains a reference to, say, a LinkedList, in addition to the correct value of the reference being visible to other threads, also the contents of that LinkedList at construction time would be visible to other threads without synchronization. The result is a significant strengthening of the meaning of final – that final fields can be safely accessed without synchronization, and that compilers can assume that final fields will not change and can therefore optimize away multiple fetches.

譯:新的 JMM 也尋求提供一種保證初始化安全的機制——只要一個對象被正確的構造出來,那么所有的線程都將能看到在其構造函數中設置的字段的值。而不管是否使用同步將引用從一個線程傳遞到了另一個線程。此外,通過正確構造的對象的 final 字段可以訪問到的任何變量,例如 final 字段引用的對象的字段,也能夠保證對其他線程可見。這意味著,如果 final 字段包含對 LinkedList 的引用,那么除了該引用的正確值對其他線程可見之外,在構造時該 LinkedList 的內容也將對其他線程可見,而無需同步。結果就是,final 字段的含義得到的顯著的增強——final 字段可以在沒有同步的情況下安全的訪問,編譯器可以認為 final字 段不會更改,因此可以進行多次優化。

Final means final(final 意味著 最終)

The mechanism by which final fields could appear to change their value under the old memory model was outlined in Part 1 – in the absence of synchronization, another thread could first see the default value for a final field and then later see the correct value.

譯:在老的內存模型中,final 字段可能會出現改變其值的機制——在沒有同步的情況下,另一個線程可能先看到 final 字段的默認值,然后才能看到正確值。

Under the new memory model, there is something similar to a happens-before relationship between the write of a final field in a constructor and the initial load of a shared reference to that object in another thread. When the constructor completes, all of the writes to final fields (and to variables reachable indirectly through those final fields) become “frozen,” and any thread that obtains a reference to that object after the freeze is guaranteed to see the frozen values for all frozen fields. Writes that initialize final fields will not be reordered with operations following the freeze associated with the constructor.

譯:在新的內存模型中,在構造函數為 final 字段賦值和在另一個線程中讀取對象的值這兩個動作之間,有一個類似 happens-before 的機制。當構造函數執行完成之后,所有對于 final 字段的寫操作都會被凍結,并且任何在凍結之后獲取對該對象的應用的線程都被保證看到是的凍結的值。對 final 字段的初始化操作并不會和凍結之后的操作進行重排序。

Summary(總結)

JSR 133 significantly strengthens the semantics of volatile, so that volatile flags can be used reliably as indicators that the program state has been changed by another thread. As a result of making volatile more “heavyweight,” the performance cost of using volatile has been brought closer to the performance cost of synchronization in some cases, but the performance cost is still quite low on most platforms. JSR 133 also significantly strengthens the semantics of final. If an object’s reference is not allowed to escape during construction, then once a constructor has completed and a thread publishes a reference to an object, that object’s final fields are guaranteed to be visible, correct, and constant to all other threads without synchronization.

譯:JSR133 顯著的增強了 volatilec關鍵字的語義,因此,volatile 現在可以可靠的標記可被其他線程修改的程序狀態。由于 volatile 在語義改變之后變得更加重量級,在某些場景下,使用 volatile 帶來的性能消耗和使用 synchronization 幾乎接近,但是在大多數 Java 平臺中 volatile 的性能消耗仍然很低。JSR133 也顯著的增強了 final 關鍵字的語義。如果一個對象的應用在構造期間不能逃逸,那么一旦構造函數完成,一個線程把引用給了一個對象,那么對應的 final 字段可以保證對于所有的線程都是可見的、正確的、并且固定的。

These changes greatly strengthen the utility of immutable objects in concurrent programs; immutable objects finally become inherently thread-safe (as they were intended to be all along), even if a data race is used to pass references to the immutable object between threads.

譯:這些變化極大地增強了并發程序中不可變對象的實用性;不可變對象最終變得本質上是線程安全的(正如它們一直以來的意圖),即使使用數據競賽在線程之間傳遞對不可變對象的引用。

The one caveat with initialization safety is that the object’s reference must not “escape” its constructor – the constructor should not publish, directly or indirectly, a reference to the object being constructed. This includes publishing references to nonstatic inner classes, and generally precludes starting threads from within a constructor. For a more detailed explanation of safe construction, see Resources.

譯:初始化安全的一個警告是,對象的引用不能“轉義”其構造函數——構造函數不能直接或間接地發布對正在構造的對象的引用。這包括發布對非靜態內部類的引用,通常不允許從構造函數內啟動線程。有關安全施工的更詳細解釋,請參閱[參考資料]。

Resources(參考資料)

  • Bill Pugh, who originally discovered many of the problems with the Java Memory Model, maintains a Java Memory Model page.
  • The issues with the old memory model and a summary of the new memory model semantics can be found in the JSR 133 FAQ.
  • Read more about the double-checked locking problem, and why the obvious attempts to fix it don’t work.
  • Read more about why you don’t want to let a reference to an object escape during construction.
  • JSR 133, charged with revising the JMM, was convened under the Java Community Process. JSR 133 has recently released its public review specification.
  • If you want to see how specifications like this are made, browse the JMM mailing list archive.
  • Concurrent Programming in Java by Doug Lea (Addison-Wesley, 1999) is a masterful book on the subtle issues surrounding multithreaded Java programming.
  • Synchronization and the Java Memory Model summarizes the actual meaning of synchronization.
  • Chapter 17 of The Java Language Specification by James Gosling, Bill Joy, Guy Steele, and Gilad Bracha (Addison-Wesley, 1996) covers the gory details of the original Java Memory Model.
  • Find hundreds more Java technology resources on the developerWorks Java technology zone.
  • Browse for books on these and other technical topics.

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/535505.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/535505.shtml
英文地址,請注明出處:http://en.pswp.cn/news/535505.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

oracle的buffercache

LRU空閑或者干凈的鏈,可以從這里找到未修改的數據LRUW臟鏈,一個臟塊同時掛到了lruw和檢查點隊列,LRUW分冷端和熱端,冷端即為更新頻率較低的一端,熱端為更新頻率較高的一端,dbwn寫入數據文件時從冷端開始寫入…

oracle的undo

Undo段中區的狀態free expiredinactiveactive 顯示UNDO區信息 SELECT extent_ id, bytes, status FROM dba_ _undo_ _extentsWHERE segment_ name SYSSMU1S ; 圖解一一個事務的操作流程 Undo段的組成:段頭、回滾塊 事務ID …

SQLPlus命令詳細說明

SQLPlus命令詳細說明 2011-10-19 17:23:01 分類: Oracle 1. 執行一個SQL腳本文件 SQL>start file_name SQL> file_name 2. 對當前的輸入進行編輯 SQL>edit 3. 重新運行上一次運行的sql語句 SQL>/ 4. 將顯示的內容輸出到指定文件 SQL> S…

oracle的EMCTL

Microsoft Windows [版本 6.1.7601] 版權所有 (c) 2009 Microsoft Corporation。保留所有權利。 C:\Users\Administrator>emctl start dbconsole Environment variable ORACLE_UNQNAME not defined. Please set ORACLE_UNQNAME to da tabase unique name. C:\Users\Administ…

RHEL7 修改SSH默認端口

1.查詢seliunx [roottest10597 ~]# getenforce Enforcing [roottest10597 ~]# semanage port -l|grep ssh ssh_port_t tcp 222.設置selinux端口 [roottest10597 ~]# semanage port -a -t ssh_port_t -p tcp 10022 [roottest10597 ~]# semanage …

oracle預定義異常

NO_DATA_FOUND:執行查詢無數據、引用一個末初使化的表、通過UTL_FILE包調用到尾的文件TOO_MANY_ROWS:采用SELECT INTO語句,但返回的記錄超過了1條DUP_VAL_ON_INDEX:插入或者更新語句,與唯一索引相沖突TIMEOUT_ON_RESOURCE:等待資源…

常用系統函數oracle

單行函數日期函數ADD_MONTHS(date, n):用于從一個日期值增加或減少一些月份 MONTHS_BETWEEN(date1, date2):判斷兩個日期之間相差的月份 LAST_DAY(date): 函數返回包含日期的月份的最后一天 ROUND(date[,fmt]): 將日期d按照fmt指定的格式舍入,fmt為字符串 TRU…

oracle游標

游標(cursor )是一個私有的SQL工作區域,是一個指向上下文區的句柄或指針,位于內存中的 "臨時表"。 游標是SQL的一個內存工作區,由系統或用戶以變量的形式定義。游標的作用就是用于臨時存儲從數據庫中提取的數據塊。在某…

找出占用cpu最高的線程

ps -eo %cpu,pid |sort -n -k1 -r | head -n 1| awk {print $2}| xargs top -b -n1 -Hp | grep COMMAND -A1 |tail -n 1 |awk {print $1}| xargs printf 0x%x ? 在命令行輸入top,然后shiftp查看占用CPU最高的進程,記下進程號 ? 在命令行輸入top -Hp…

系統學習SpringFramework:Spring 概述

本篇內容包括:Spring/SpringFrame 概述、Spring IOC 和 AOP 概述、Spring 全家桶內容概述(包括:Spring Boot、Spring Cloud、Spring Cloud data flow …)等內容! 一、Spring/SpringFrame 概述 Spring 是一個生態體系&…

存儲過程與函數oracle

存儲在數據庫中供所有用戶程序調用的子程序叫做存儲過程,存儲函數。 存儲過程是在大型數據庫系統中,用PL/SQL語言編寫的能完成一定處理功能的存儲在數據庫字典中的程序,它是一個命名的 PL/SQL 塊,經編譯后存儲在數據庫中&#xff…

系統學習SpringFramework:Spring IOC

本篇內容包括:IOC 和 DI 的概念、Spring 容器,即 BenaFactory 與 AplicationConext 等 IOC 相關內容。 一、IOC 和 DI 的概念 1、IOC IoC(Inversion of control )即“控制反轉”,它是一種設計思想而非一個技術實現。…

徹底卸載oracle

linux刪除Oracle安裝目錄下的所有文件和文件夾即可。windows 1.關閉oracle所有的服務。可以在windows的服務管理器中關閉 2.打開注冊表:regedit 打開路徑: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ 刪除該路徑下的所有以oracle開始的服務…

系統學習SpringFramework:Spring AOP

本篇內容包括:Spring AOP 概述(AOP 簡介、AOP 為什么叫面向切面編程、AOP 主要用來解決的問題 和 AOP 的相關術語)、Spring AOP Demo(xml 方式、注解方式)以及相關知識點(JDK 動態代理和 CGLIB 代理、Sprin…

rowid

ROWID的格式rowidOOOOOOFFFBBBBBBRRR說明數據對象號相對文件號數據塊號行號 上述表格是Oracle 9i及以上版本數據庫中的rowid格式: 6位對象號3位相對文件號6位數據塊號3位行號,是一個18位的64進制值。這個18位的64進制值在數據庫內卻是以10個bytes合計80個bit的二進制…

git和gitlab安裝

1.下載git最新包 https://mirrors.edge.kernel.org/pub/software/scm/git/ 將最新包上傳至服務器/home目錄 tar -Jxvf 解壓 進入git目錄 ./configure --prefix/usr/local/git make make install 錯誤解決:Cant locate ExtUtils/MakeMaker.pm in INC yum i…

系統學習SpringFramework:循環依賴與三級緩存

本篇內容包括:Spring 中的循環依賴問題(包括 Spring 中的循環依賴問題和Spring 中的循環依賴的 5 種場景的介紹)、Spring 三級緩存介紹、4 個 Spring 無法自動解決的循環以來場景以及其對應的手動解決方式。 一、Spring 中的循環依賴問題 1、…

oracle安裝需要的包列表

redhat7.5安裝圖形界面: [rootwwyt ~]# rpm -ivh --nodeps --force xorg-x11-font* [rootwwyt ~]# mount -o loop -t iso9660 rhel-server-7.5-x86_64-dvd.iso /media/iso/ [rootwwyt ~]# cat /etc/yum.repos.d/my.repo [base] nameredhat7.5 baseurlfile:///m…

深入理解Java虛擬機:Java類的加載機制

本篇內容包括:Java 類的加載機制(Jvm 結構組成、Java 類的加載)、類的生命周期(加載-驗證-準備-解析-初始化-使用-卸載)、類加載器 以及 雙親委派模型。 一、Java 類的加載機制 1、 Jvm 結構組成 Jvm 整體組成可分為…

新版谷歌瀏覽器開啟Flash支持

瀏覽器地址欄中輸入chrome://version查看Chrome瀏覽器、Flash插件的版本信息。 Chrome 69.0-70.0版本Chrome 71.0-74.0及以后版本谷歌瀏覽器地址欄中輸入【chrome://flags/#enable-ephemeral-flash-permission】,將【Enable Ephemeral Flash Permissions】從【Defau…