Intorduction | About Threaded Programming | Thread Management | Run Loops
Synchronization | Thread Safety Summary | Glossary

본 페이지는 Threading Programming Guide 문서의 Thread Management 부분을 번역해 놓은 페이지 입니다. 발 번역이라 이상한 부분이 있을 수 있습니다. 발견즉시 댓글을 달아 주세요.



Thread Management
스레드 관리

Each process (application) in OS X or iOS is made up of one or more threads, each of which represents a single path of execution through the application's code. Every application starts with a single thread, which runs the application's main function. Applications can spawn additional threads, each of which executes the code of a specific function.

OS X 또는 IOS의 각 프로세스 (응용 프로그램) 응용 프로그램 코드를 통해 실행의 단일 경로를 각각 나타내는 하나 이상의 스레드로 구성됩니다. 모든 응용 프로그램은 응용 프로그램의 주요 기능을 실행하는 단일 스레드로 시작합니다. 응용 프로그램은 특정 함수의 코드를 실행 각각의 추가 스레드를 생성 할 수 있습니다.

When an application spawns a new thread, that thread becomes an independent entity inside of the application's process space. Each thread has its own execution stack and is scheduled for runtime separately by the kernel. A thread can communicate with other threads and other processes, perform I/O operations, and do anything else you might need it to do. Because they are inside the same process space, however, all threads in a single application share the same virtual memory space and have the same access rights as the process itself.

응용 프로그램이 새 스레드를 생성하면 해당 스레드는 응용 프로그램의 프로세스 공간 내부에 독립적 인 엔티티됩니다. 각 스레드는 자신의 실행 스택을 가지고 있으며, 커널이 별도로 런타임 예정이다.스레드는 다른 스레드와 다른 프로세스와 통신 I / O 작업을 수행하고 당신이 할을해야 할 수도 있습니다 다른 작업을 수행 할 수 있습니다. 그들은 동일한 프로세스 공간 내부에 있기 때문에 그러나, 하나의 응용 프로그램의 모든 스레드가 동일한 가상 메모리 공간을 공유하고 프로세스 자체와 동일한 액세스 권한을가집니다.

This chapter provides an overview of the thread technologies available in OS X and iOS along with examples of how to use those technologies in your applications.

이 장에서는 응용 프로그램에서 이러한 기술을 사용하는 방법에 대한 예제와 함께 OS X 및 IOS에서 사용할 수있는 스레드 기술의 개요를 제공합니다.

Thread Costs
스레드 비용

Threading has a real cost to your program (and the system) in terms of memory use and performance. Each thread requires the allocation of memory in both the kernel memory space and your program’s memory space. The core structures needed to manage your thread and coordinate its scheduling are stored in the kernel using wired memory. Your thread’s stack space and per-thread data is stored in your program’s memory space. Most of these structures are created and initialized when you first create the thread—a process that can be relatively expensive because of the required interactions with the kernel.

스레딩 메모리 사용과 성능면에서 프로그램에 실제 비용 (및 시스템)가 있습니다. 각 스레드는 커널 메모리 공간과 프로그램의 메모리 공간 모두에서 메모리 할당이 필요합니다. 귀하의 스레드를 관리하고 일정을 조정하는 데 필요한 핵심 구조는 유선 메모리를 사용하여 커널에 저장됩니다. 귀하의 스레드의 스택 공간과 스레드 당 데이터는 프로그램의 메모리 공간에 저장됩니다. 이러한 구조의 대부분은 생성하고 처음 있기 때문에 커널에 필요한 상호 작용의 상대적으로 비쌀 수 있습니다 스레드 프로세스를 만들 때 초기화됩니다.

Table 2-1 quantifies the approximate costs associated with creating a new user-level thread in your application. Some of these costs are configurable, such as the amount of stack space allocated for secondary threads. The time cost for creating a thread is a rough approximation and should be used only for relative comparisons with each other. Thread creation times can vary greatly depending on processor load, the speed of the computer, and the amount of available system and program memory.

표 2-1는 응용 프로그램에서 새 사용자 수준 스레드를 생성과 관련된 대략적인 비용을 정량화. 이러한 비용 중 일부는 보조 스레드에 할당 된 스택 공간으로 구성 할 수 있습니다.스레드를 만들기위한 시간 비용은 대략적이며, 서로 상대 비교에만 사용되어야한다. 스레드 생성 시간은 프로세서 부하, 컴퓨터의 속도 및 사용 가능한 시스템 및 프로그램 메모리의 양에 따라 크게 달라질 수 있습니다.

Table 2-1  Thread creation costs

Item

Approximate cost

Notes

Kernel data structures

Approximately 1 KB

This memory is used to store the thread data structures and attributes, much of which is allocated as wired memory and therefore cannot be paged to disk.

이 메모리는 유선 메모리를 할당하기 때문에 디스크에 페이징 할 수없는 다량의이 스레드 데이터 구조와 특성을 저장하는 데 사용됩니다.

Stack space

512 KB (secondary threads)

8 MB (OS X main thread)

1 MB (iOS main thread)

The minimum allowed stack size for secondary threads is 16 KB and the stack size must be a multiple of 4 KB. The space for this memory is set aside in your process space at thread creation time, but the actual pages associated with that memory are not created until they are needed.

보조 스레드 허용되는 최소 스택 크기는 16 KB입니다 및 스택 크기는 4 KB를 배수 여야합니다. 이 메모리 공간은 스레드 생성시 프로세스 공간에 따로 설정되어 있지만, 필요할 때까지 메모리 연결된 실제 페이지가 생성되지 않습니다.

Creation time

Approximately 90 microseconds

This value reflects the time between the initial call to create the thread and the time at which the thread’s entry point routine began executing. The figures were determined by analyzing the mean and median values generated during thread creation on an Intel-based iMac with a 2 GHz Core Duo processor and 1 GB of RAM running OS X v10.5.

이 값은 스레드와 스레드의 진입 점 루틴이 실행을 시작하는 시간을 만들기 위해 초기 호출 사이의 시간을 반영합니다.수치는 OS X 10.5을 실행 2 GHz의 코어 듀오 프로세서와 1GB의 RAM과 인텔 기반 아이맥에 스레드를 만드는 동안 생성 된 평균과 중간 값을 분석하여 결정 하였다.

Another cost to consider when writing threaded code is the production costs. Designing a threaded application can sometimes require fundamental changes to the way you organize your application’s data structures. Making those changes might be necessary to avoid the use of synchronization, which can itself impose a tremendous performance penalty on poorly designed applications. Designing those data structures, and debugging problems in threaded code, can increase the time it takes to develop a threaded application. Avoiding those costs can create bigger problems at runtime, however, if your threads spend too much time waiting on locks or doing nothing.

스레드 코드를 작성할 때 고려해야 할 또 다른 비용은 생산 비용이다.스레드 응용 프로그램을 설계하는 것은 때로는 응용 프로그램의 데이터 구조를 구성하는 방식에 근본적인 변화를 요구할 수 있습니다. 이러한 변화를 만드는 것은 그 자체가 잘못 설계된 응용 프로그램에 엄청난 성능 저하를 부과 할 동기의 사용을 방지 할 필요가 있습니다. 이러한 데이터 구조를 설계하고, 스레드 코드의 문제를 디버깅, 그것은 스레드 응용 프로그램을 개발하는 데 소요되는 시간을 늘릴 수 있습니다. 귀하의 스레드가 잠금을 대기하거나 아무것도하지 않고 너무 많은 시간을 소비하는 경우 그 비용을 피하는 것은, 그러나, 런타임에 더 큰 문제를 만들 수 있습니다.

Creating a Thread
스레드 만들기

Creating low-level threads is relatively simple. In all cases, you must have a function or method to act as your thread’s main entry point and you must use one of the available thread routines to start your thread. The following sections show the basic creation process for the more commonly used thread technologies. Threads created using these techniques inherit a default set of attributes, determined by the technology you use. For information on how to configure your threads, see“Configuring Thread Attributes.”

낮은 수준의 스레드를 생성하는 것은 비교적 간단합니다. 모든 경우에, 당신은 기능 또는 스레드의 주 진입 점 역할을하는 방법이 있어야합니다 그리고 당신은 당신의 스레드를 시작하는 데 사용할 수있는 스레드 루틴 중 하나를 사용해야합니다.다음 섹션에서는 일반적으로 사용되는 스레드 기술에 대한 기본 생성 과정을 보여줍니다. 스레드는이 기술을 사용하는 기술에 의해 결정 속성의 기본 세트를 상속하여 만들었습니다. 귀하의 스레드를 구성하는 방법에 대한 자세한 내용은 "스레드 속성 구성"을 참조하십시오.

Using NSThread

NSThread를 사용하여

There are two ways to create a thread using the NSThread class:
NSThread 클래스를 사용하여 스레드를 생성하는 방법은 두 가지가 있습니다 :

  • Use the detachNewThreadSelector:toTarget:withObject: class method to spawn the new thread.
    detachNewThreadSelector를 사용 toTarget : withObject : 새로운 스레드를 생성하는 클래스 메서드.

  • Create a new NSThread object and call its start method. (Supported only in iOS and OS X v10.5 and later.)
    새로운 NSThread 객체를 생성하고 시작 메서드를 호출합니다. (단 IOS 및 OS X 10.5 이상에서만 지원됩니다.)

Both techniques create a detached thread in your application. A detached thread means that the thread’s resources are automatically reclaimed by the system when the thread exits. It also means that your code does not have to join explicitly with the thread later.

두 기술은 응용 프로그램에서 분리 된 스레드를 만들 수 있습니다.분리 된 스레드는 스레드의 리소스가 자동으로 시스템 스레드 종료를 회수하는 것을 의미합니다. 그것은 또한 당신의 코드는 나중에 스레드 명시 적으로 참여하지 않는다는 것을 의미합니다.

Because the detachNewThreadSelector:toTarget:withObject: method is supported in all versions of OS X, it is often found in existing Cocoa applications that use threads. To detach a new thread, you simply provide the name of the method (specified as a selector) that you want to use as the thread’s entry point, the object that defines that method, and any data you want to pass to the thread at startup. The following example shows a basic invocation of this method that spawns a thread using a custom method of the current object.

때문에 detachNewThreadSelector : toTarget : withObject : 방법은 OS X의 모든 버전에서 지원됩니다, 그것은 종종 스레드를 사용하는 기존의 코코아 응용 프로그램에서 찾을 수 있습니다.새 스레드를 분리하려면, 당신은 단순히 당신이 스레드의 진입 점, 해당 메서드를 정의하는 개체로 사용할 메소드의 이름 (선택으로 지정), 당신은 시작할 때 스레드에 전달하려는 모든 데이터를 제공 . 다음 예제에서는 현재 개체의 사용자 지정 메서드를 사용하여 스레드를 생성이 방법의 기본 호출을 보여줍니다.

[NSThread detachNewThreadSelector:@selector(myThreadMainMethod:) toTarget:self withObject:nil];

Prior to OS X v10.5, you used the NSThread class primarily to spawn threads. Although you could get an NSThread object and access some thread attributes, you could only do so from the thread itself after it was running. In OS X v10.5, support was added for creating NSThread objects without immediately spawning the corresponding new thread. (This support is also available in iOS.) This support made it possible to get and set various thread attributes prior to starting the thread. It also made it possible to use that thread object to refer to the running thread later.

OS X v10.5 이전, 당신은 주로 스레드를 생성하는 NSThread 클래스를 사용했습니다. 당신은 NSThread 객체를 얻을 몇 가지 스레드 속성에 액세스 할 수 있지만 그것을 실행 된 후에, 당신은 단지 스레드 자체에서 그렇게 할 수 있습니다. OS X 10.5에서 지원을 즉시 산란 해당 새 스레드없이 NSThread 객체를 만들기 위해 추가되었습니다. (이 지원은 IOS에서 사용할 수 있습니다.)이 지원이 스레드를 시작에 도착하고 사전에 다양한 스레드 속성을 설정하는 것이 가능했다. 그것은 또한 가능한 나중에 실행중인 스레드를 참조하는 해당 스레드 객체를 사용했다.

The simple way to initialize an NSThread object in OS X v10.5 and later is to use the initWithTarget:selector:object: method. This method takes the exact same information as the detachNewThreadSelector:toTarget:withObject: method and uses it to initialize a new NSThread instance. It does not start the thread, however. To start the thread, you call the thread object’s start method explicitly, as shown in the following example:

선택 : 객체 방법 : OS X 10.5 이상에서 NSThread 객체를 초기화하는 간단한 방법은 initWithTarget를 사용하는 것입니다. toTarget : withObject :이 방법은 detachNewThreadSelector과 정확히 동일한 정보 걸리는 방법을 새로운 NSThread 인스턴스를 초기화하는 데 사용합니다. 그것은 그러나, 스레드를 시작하지 않습니다. 다음 예제와 같이 스레드를 시작하려면, 당신은 명시 적으로 스레드 객체의 start 메소드를 호출

NSThread* myThread = [[NSThread alloc] initWithTarget:self
                                        selector:@selector(myThreadMainMethod:)
                                        object:nil];
[myThread start];  // Actually create the thread

If you have an NSThread object whose thread is currently running, one way you can send messages to that thread is to use theperformSelector:onThread:withObject:waitUntilDone: method of almost any object in your application. Support for performing selectors on threads (other than the main thread) was introduced in OS X v10.5 and is a convenient way to communicate between threads. (This support is also available in iOS.) The messages you send using this technique are executed directly by the other thread as part of its normal run-loop processing. (Of course, this does mean that the target thread has to be running in its run loop; see “Run Loops.”) You may still need some form of synchronization when you communicate this way, but it is simpler than setting up communications ports between the threads.

당신은 누구의 스레드 현재 실행중인 NSThread 객체를 가지고 있다면, 당신은 해당 스레드에 메시지를 보낼 수있는 한 가지 방법은 theperformSelector 사용하는 것입니다 onThread : withObject : waitUntilDone : 응용 프로그램의 거의 모든 객체의 메서드입니다. 스레드 (주 스레드가 아닌)에서 선택기를 수행하기위한 지원 OS X 10.5에서 소개하고 스레드간에 통신 할 수있는 편리한 방법입니다. 한 (이 지원은 IOS에서 사용할 수 있습니다.)이 기술을 사용하여 전송되는 메시지는 정상적인 실행 루프 처리의 일부로서 다른 스레드에서 직접 실행됩니다. 이 방법으로 의사 소통을 할 때 당신은 아직도 동기화의 일부 양식을해야 할 수도 있지만, 통신 포트에게 설정보다 간단합니다; (참조 "실행 루프를."물론,이 타겟 thread의 실행 루프에서 실행해야하는 것을 의미)스레드 사이.

For a list of other thread communication options, see “Setting the Detached State of a Thread.”
다른 thread가 통신 옵션의 목록을 보려면 "스레드의 분리 상태 설정"을 참조하십시오.

Using POSIX Threads

POSIX 스레드를 사용하여

OS X and iOS provide C-based support for creating threads using the POSIX thread API. This technology can actually be used in any type of application (including Cocoa and Cocoa Touch applications) and might be more convenient if you are writing your software for multiple platforms. The POSIX routine you use to create threads is called, appropriately enough, pthread_create.

OS X 및 IOS는 POSIX 스레드 API를 사용하여 스레드를 생성하기위한 C 기반의 지원을 제공합니다. 이 기술은 실제로 모든 유형의 응용 프로그램에서 사용할 수 있습니다 (코코아와 코코아 터치 응용 프로그램 포함) 여러 플랫폼을위한 소프트웨어를 작성하는 경우 더 편리 할 수 있습니다. 스레드를 만드는 데 사용하는 POSIX 루틴가 pthread_create, 적절하게 충분히이라고합니다.

Listing 2-1 shows two custom functions for creating a thread using POSIX calls. The LaunchThread function creates a new thread whose main routine is implemented in the PosixThreadMainRoutine function. Because POSIX creates threads as joinable by default, this example changes the thread’s attributes to create a detached thread. Marking the thread as detached gives the system a chance to reclaim the resources for that thread immediately when it exits.

목록 2-1 POSIX 호출을 사용하여 스레드를 생성하기위한 두 개의 사용자 지정 함수를 보여줍니다.LaunchThread 함수는 누구의 주요 루틴 PosixThreadMainRoutine 함수에서 구현되는 새로운 스레드를 만듭니다. POSIX는 기본적으로 조인으로 스레드를 생성하기 때문에이 예제는 분리 된 스레드를 생성하는 스레드의 속성을 변경합니다. 분리로 스레드를 표시하면 시스템에게이 스레드 리소스를 확보 할 수있는 기회를 제공 곧바로 때 종료됩니다.

Listing 2-1  Creating a thread in C

#include <assert.h>
#include <pthread.h>
 
void* PosixThreadMainRoutine(void* data)
{
    // Do some work here.
 
    return NULL;
}
 
void LaunchThread()
{
    // Create the thread using POSIX routines.
    pthread_attr_t  attr;
    pthread_t       posixThreadID;
    int             returnVal;
 
    returnVal = pthread_attr_init(&attr);
    assert(!returnVal);
    returnVal = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    assert(!returnVal);
 
    int     threadError = pthread_create(&posixThreadID, &attr, &PosixThreadMainRoutine, NULL);
 
    returnVal = pthread_attr_destroy(&attr);
    assert(!returnVal);
    if (threadError != 0)
    {
         // Report an error.
    }
}

If you add the code from the preceding listing to one of your source files and call the LaunchThread function, it would create a new detached thread in your application. Of course, new threads created using this code would not do anything useful. The threads would launch and almost immediately exit. To make things more interesting, you would need to add code to the PosixThreadMainRoutine function to do some actual work. To ensure that a thread knows what work to do, you can pass it a pointer to some data at creation time. You pass this pointer as the last parameter of the pthread_create function.

당신은 위의 목록에서 소스 파일 중 하나에 코드를 추가 LaunchThread의 함수를 호출하면 응용 프로그램에서 새로운 분리 된 스레드를 만듭니다. 물론,이 코드를 사용하여 만든 새 스레드 유용한 아무것도하지 않을 것입니다.스레드가 시작하고 거의 즉시 종료됩니다. 상황이 더 흥미로운 만들기 위해, 당신은 몇 가지 실제 작업을 수행 할 PosixThreadMainRoutine 함수에 코드를 추가해야합니다.스레드가 할 일이 무엇을 알고 있는지 확인하려면, 당신은 그것을 생성시 일부 데이터에 대한 포인터를 전달할 수 있습니다. 당신은가 pthread_create 함수의 마지막 매개 변수로이 포인터를 전달합니다.

To communicate information from your newly created thread back to your application’s main thread, you need to establish a communications path between the target threads. For C-based applications, there are several ways to communicate between threads, including the use of ports, conditions, or shared memory. For long-lived threads, you should almost always set up some sort of inter-thread communications mechanism to give your application’s main thread a way to check the status of the thread or shut it down cleanly when the application exits.

응용 프로그램의 주 스레드에 새로 생성 된 스레드를 다시에서 정보를 전달하기 위해, 당신은 대상 스레드 간의 통신 경로를 설정해야합니다. C 기반 응용 프로그램, 포트, 조건, 또는 공유 메모리의 사용을 포함하여 스레드간에 통신하는 방법에는 여러 가지가 있습니다. 수명이 긴 스레드, 당신은 거의 항상 스레드 간 통신의 일종 응용 프로그램의 주 스레드에게 스레드의 상태를 확인하거나 응용 프로그램이 종료 할 때 청결하게 종료하는 방법을 제공하는 메커니즘을 설정해야합니다.

For more information about POSIX thread functions, see the pthread man page.
POSIX 쓰레드 함수에 대한 자세한 내용은 pthread에 매뉴얼 페이지를 참조하십시오.

Using NSObject to Spawn a Thread

스레드를 생성하는 NSObject의 사용

In iOS and OS X v10.5 and later, all objects have the ability to spawn a new thread and use it to execute one of their methods. TheperformSelectorInBackground:withObject: method creates a new detached thread and uses the specified method as the entry point for the new thread. For example, if you have some object (represented by the variable myObj) and that object has a method called doSomething that you want to run in a background thread, you could use the following code to do that:

IOS 나중에 OS X 10.5 이상에서는 모든 개체는 새로운 스레드를 생성하고 해당 메서드 중 하나를 실행하는 데 사용하는 기능이 있습니다. TheperformSelectorInBackground : withObject : 메서드는 새로운 분리 된 스레드를 생성하고 새 스레드의 진입 점으로 지정된 메서드를 사용합니다. 당신은 어떤 객체 (변수하여 MyObj로 표현)가 있고 그 객체는 백그라운드 스레드에서 실행하려는 해봐요라는 메서드가있는 경우 예를 들어, 당신은 그렇게 할 다음 코드를 사용할 수 있습니다 :

[myObj performSelectorInBackground:@selector(doSomething) withObject:nil];

The effect of calling this method is the same as if you called the detachNewThreadSelector:toTarget:withObject: method of NSThread with the current object, selector, and parameter object as parameters. The new thread is spawned immediately using the default configuration and begins running. Inside the selector, you must configure the thread just as you would any thread. For example, you would need to set up an autorelease pool (if you were not using garbage collection) and configure the thread’s run loop if you planned to use it. For information on how to configure new threads, see “Configuring Thread Attributes.”

당신이 detachNewThreadSelector를 호출하면이 메소드를 호출의 효과는 동일합니다 toTarget : withObject : 현재 개체를 선택하고 매개 변수로 매개 변수 개체를 NSThread의 방법.새 스레드는 기본 구성을 사용하여 즉시 양산 및 실행을 시작합니다.선택 안에, 당신은 당신이 어떤 스레드와 마찬가지로 스레드를 구성해야합니다. 예를 들어, autorelease를 풀 (당신은 가비지 수집을 사용하지 않은 경우)을 설정하고 당신이 그것을 사용하는 계획하는 경우 스레드의 실행 루프를 구성해야합니다. 새 스레드를 구성하는 방법에 대한 자세한 내용은 "스레드 속성 구성"을 참조하십시오.

Using POSIX Threads in a Cocoa Application

코코아 응용 프로그램에서 POSIX 스레드를 사용하여

Although the NSThread class is the main interface for creating threads in Cocoa applications, you are free to use POSIX threads instead if doing so is more convenient for you. For example, you might use POSIX threads if you already have code that uses them and you do not want to rewrite it. If you do plan to use the POSIX threads in a Cocoa application, you should still be aware of the interactions between Cocoa and threads and obey the guidelines in the following sections.

NSThread 클래스는 코코아 응용 프로그램에서 스레드를 생성하기위한 주요 인터페이스이지만, 당신은 이렇게하면 당신을 위해 더 편리한 경우 대신 POSIX 스레드를 사용하여 무료입니다. 당신이 이미 그들을 사용하는 코드를 가지고 당신이 그것을 다시하지 않으려면 예를 들어, POSIX 스레드를 사용할 수 있습니다. 당신은 코코아 응용 프로그램에서 POSIX 스레드를 사용하여 계획을 할 경우, 당신은 여전히 ​​코코아와 스레드 간의 상호 작용을 인식하고 다음 섹션의 지침을 준수해야합니다.

Protecting the Cocoa Frameworks
코코아 프레임 워크를 보호

For multithreaded applications, Cocoa frameworks use locks and other forms of internal synchronization to ensure they behave correctly. To prevent these locks from degrading performance in the single-threaded case, however, Cocoa does not create them until the application spawns its first new thread using the NSThreadclass. If you spawn threads using only POSIX thread routines, Cocoa does not receive the notifications it needs to know that your application is now multithreaded. When that happens, operations involving the Cocoa frameworks may destabilize or crash your application.

다중 스레드 응용 프로그램의 경우, 코코아 프레임 워크들이 제대로 동작하기 위해 잠금 및 내부 동기화의 다른 형태를 사용합니다. 응용 프로그램이 NSThreadclass를 사용하여 먼저 새로운 스레드를 생성 할 때까지 단일 스레드의 경우 성능 저하에서 이러한 잠금을 방지하기 위해, 그러나, 코코아를 작성하지 않습니다. 당신은 POSIX 스레드 루틴을 사용하여 스레드를 생성하는 경우, 코코아는 응용 프로그램이 다중 스레드 것을 알 필요가 알림을받지 않습니다. 그렇게되면, 코코아 프레임 워크와 관련된 작업은 응용 프로그램을 불안정하거나 중단 될 수 있습니다.

To let Cocoa know that you intend to use multiple threads, all you have to do is spawn a single thread using the NSThread class and let that thread immediately exit. Your thread entry point need not do anything. Just the act of spawning a thread using NSThread is enough to ensure that the locks needed by the Cocoa frameworks are put in place.

코코아는 여러 스레드를 사용하고자하는 알 수 있도록, 당신이해야 할 모든 NSThread 클래스를 사용하여 단일 스레드를 생성하고 스레드가 즉시 종료하게됩니다. 귀하의 스레드 엔트리 포인트는 아무것도 할 필요가 없습니다. 산란 단지 행위는 NSThread를 사용하여 스레드는 코코아 프레임 워크에 필요한 잠금 위치에 배치되어 있는지 확인하기 위해 충분하다.

If you are not sure if Cocoa thinks your application is multithreaded or not, you can use the isMultiThreaded method of NSThread to check.

코코아 응용 프로그램이 다중 스레드인지 생각하면 당신이 확실하지 않은 경우, 당신은 확인 NSThread의 isMultiThreaded 방법을 사용할 수 있습니다.

Mixing POSIX and Cocoa Locks

POSIX와 코코아 잠금을 혼합

It is safe to use a mixture of POSIX and Cocoa locks inside the same application. Cocoa lock and condition objects are essentially just wrappers for POSIX mutexes and conditions. For a given lock, however, you must always use the same interface to create and manipulate that lock. In other words, you cannot use a CocoaNSLock object to manipulate a mutex you created using the pthread_mutex_init function, and vice versa.

같은 응용 프로그램 내에서 POSIX와 코코아 락의 혼합물을 사용하는 것이 안전하다. 코코아 잠금 상태 객체는 본질적으로 POSIX 뮤텍스와 조건에 대한 래퍼입니다. 주어진 잠금, 그러나, 당신은 항상 잠금을 생성하고 조작하는 동일한 인터페이스를 사용해야합니다. 즉, 당신은 당신이 pthread_mutex_init는 함수를 사용하여 만든 뮤텍스 반대를 조작 할 수 CocoaNSLock 개체를 사용할 수 없습니다.

Configuring Thread Attributes
스레드 속성 구성

After you create a thread, and sometimes before, you may want to configure different portions of the thread environment. The following sections describe some of the changes you can make and when you might make them.
당신이 스레드를 생성하고, 때로는 이전 후에는 스레드 환경의 다른 부분을 구성 할 수 있습니다.다음 섹션에서는 당신이 할 수있는 변경 사항 중 일부를 설명하고 당신이 그 (것)들을 만들 수있는 경우에.

Configuring the Stack Size of a Thread

스레드의 스택 크기 구성

For each new thread you create, the system allocates a specific amount of memory in your process space to act as the stack for that thread. The stack manages the stack frames and is also where any local variables for the thread are declared. The amount of memory allocated for threads is listed in “Thread Costs.”

당신이 만든 각 새 스레드를 들어, 시스템은 해당 스레드에 대한 스택 역할을 프로세스 공간에서 특정 양의 메모리를 할당합니다.스택은 스택 프레임을 관리하고 스레드 로컬 변수가 선언 된 곳도있다. 스레드에 할당 된 메모리의 양에 나와있는 "스레드 비용."

If you want to change the stack size of a given thread, you must do so before you create the thread. All of the threading technologies provide some way of setting the stack size, although setting the stack size using NSThread is available only in iOS and OS X v10.5 and later. Table 2-2 lists the different options for each technology.

당신은 지정된 스레드의 스택 크기를 변경하려는 경우에는 스레드를 작성하기 전에, 당신은 그렇게해야합니다. NSThread를 사용하여 스택 크기를 설정하면 전용 IOS하고 OS X 10.5 이상에서만 사용할 수 있지만 스레딩 기술의 모든, 스택 크기를 설정하는 몇 가지 방법을 제공합니다. 표 2-2은 각 기술에 대한 다른 옵션을 나열합니다.

Table 2-2  Setting the stack size of a thread

Technology

Option

Cocoa

In iOS and OS X v10.5 and later, allocate and initialize an NSThread object (do not use thedetachNewThreadSelector:toTarget:withObject: method). Before calling the start method of the thread object, use thesetStackSize: method to specify the new stack size.

IOS 및 OS X 10.5 이상에서 할당하고 NSThread 객체 (thedetachNewThreadSelector 사용하지 마십시오 toTarget : withObject : 방법)을 초기화합니다.스레드 객체의 start 메소드를 호출하기 전에, thesetStackSize를 사용하는 방법 : 새 스택 크기를 지정합니다.

POSIX

Create a new pthread_attr_t structure and use the pthread_attr_setstacksize function to change the default stack size. Pass the attributes to the pthread_create function when creating your thread.

새로운 위해서는 pthread_attr_t 구조를 생성하고 기본 스택 크기를 변경하려면 pthread_attr_setstacksize 함수를 사용합니다. 귀하의 스레드를 생성 할 때가 pthread_create 함수에 속성을 전달합니다.

Multiprocessing Services

Pass the appropriate stack size value to the MPCreateTask function when you create your thread.
당신의 스레드를 만들 MPCreateTask 기능에 대한 적절한 스택 크기 값을 전달합니다.

Configuring Thread-Local Storage

스레드 로컬 저장소 구성

Each thread maintains a dictionary of key-value pairs that can be accessed from anywhere in the thread. You can use this dictionary to store information that you want to persist throughout the execution of your thread. For example, you could use it to store state information that you want to persist through multiple iterations of your thread’s run loop.

각 스레드는 어디 스레드에서 액세스 할 수있는 키 - 값 쌍의 사전을 유지합니다. 당신은 당신의 스레드의 실행을 통해 유지하고자하는 정보를 저장하기 위해이 사전을 사용할 수 있습니다. 예를 들어, 당신은 당신의 스레드의 실행 루프를 여러 번 반복을 통해 유지하려는 상태 정보를 저장하는 데 사용할 수 있습니다.

Cocoa and POSIX store the thread dictionary in different ways, so you cannot mix and match calls to the two technologies. As long as you stick with one technology inside your thread code, however, the end results should be similar. In Cocoa, you use the threadDictionary method of an NSThread object to retrieve anNSMutableDictionary object, to which you can add any keys required by your thread. In POSIX, you use the pthread_setspecific and pthread_getspecificfunctions to set and get the keys and values of your thread.

코코아와 POSIX 저장 다른 방법으로 스레드 사전, 그래서 당신은 혼합 두 기술에 대한 호출을 일치시킬 수 없습니다. 로 당신이 당신의 스레드 코드 내부에 하나의 기술을 스틱으로, 그러나 최종 결과는 ​​비슷해야합니다. 코코아, 당신은 anNSMutableDictionary 개체를 검색 할에 당신의 스레드에 필요한 키를 추가 할 수 있습니다 NSThread 객체의 threadDictionary 메서드를 사용합니다. POSIX에서, 당신은 당신의 스레드의 키와 값을 설정하고 가져 pthread_setspecific 및 pthread_getspecificfunctions를 사용합니다.

Setting the Detached State of a Thread

스레드의 분리 상태 설정

Most high-level thread technologies create detached threads by default. In most cases, detached threads are preferred because they allow the system to free up the thread’s data structures immediately upon completion of the thread. Detached threads also do not require explicit interactions with your program. The means of retrieving results from the thread is left to your discretion. By comparison, the system does not reclaim the resources for joinable threads until another thread explicitly joins with that thread, a process which may block the thread that performs the join.

가장 높은 수준의 스레드 기술은 기본적으로 분리 된 스레드를 만들 수 있습니다. 그들은 시스템이 스레드의 완료 즉시 스레드의 데이터 구조를 확보 할 수 있기 때문에 대부분의 경우, 분리 된 스레드가 바람직하다. 분리 된 스레드는 프로그램에 명시 적으로 상호 작용을 필요로하지 않습니다.스레드에서 결과를 검색하는 방법은 재량에 남아 있습니다. 다른 스레드가 명시 적으로 해당 스레드와 조인을 수행하는 스레드를 차단할 수있는 프로세스를 조인 할 때까지 비교함으로써, 시스템이 결합 가능한 스레드 자원을 재생하지 않습니다.

You can think of joinable threads as akin to child threads. Although they still run as independent threads, a joinable thread must be joined by another thread before its resources can be reclaimed by the system. Joinable threads also provide an explicit way to pass data from an exiting thread to another thread. Just before it exits, a joinable thread can pass a data pointer or other return value to the pthread_exit function. Another thread can then claim this data by calling the pthread_joinfunction.

당신은 자식 스레드에 가깝다으로 결합 가능한 스레드를 생각할 수 있습니다. 그들은 여전히 ​​독립적 인 스레드로 실행되지만 자원이 시스템에 의해 회수 될 수 있기 전에, 조인 스레드가 다른 스레드에 가입해야합니다. 결합 가능한 스레드는 다른 스레드 종료 스레드에서 데이터를 전달하는 명시적인 방법을 제공합니다. 그냥 종료되기 전에, 조인 스레드는 데이터 포인터 또는 pthread_exit 함수에 다른 반환 값을 전달할 수 있습니다. 다른 스레드는 pthread_joinfunction를 호출하여이 데이터를 청구 할 수 있습니다.

If you do want to create joinable threads, the only way to do so is using POSIX threads. POSIX creates threads as joinable by default. To mark a thread as detached or joinable, modify the thread attributes using the pthread_attr_setdetachstate function prior to creating the thread. After the thread begins, you can change a joinable thread to a detached thread by calling the pthread_detach function. For more information about these POSIX thread functions, see the pthread man page. For information on how to join with a thread, see the pthread_join man page.

당신이 결합 가능한 스레드를 생성 할 경우, 그렇게 할 수있는 유일한 방법은 POSIX 스레드를 사용하고 있습니다. POSIX는 기본적으로 조인으로 스레드를 만듭니다. 분리 또는 조인과 같은 스레드를 표시하려면 스레드는 이전 스레드를 만드는 pthread_attr_setdetachstate 기능을 사용하여 속성을 수정합니다. 스레드가 시작되면, 당신은에 pthread_detach 함수를 호출하여 분리 된 스레드에 결합 가능한 스레드를 변경할 수 있습니다. 이러한 POSIX 쓰레드 함수에 대한 자세한 내용은 pthread에 매뉴얼 페이지를 참조하십시오.스레드와 조인하는 방법에 대한 자세한 내용까지 pthread_join 매뉴얼 페이지를 참조하십시오.

Setting the Thread Priority

스레드 우선 순위 설정

Any new thread you create has a default priority associated with it. The kernel’s scheduling algorithm takes thread priorities into account when determining which threads to run, with higher priority threads being more likely to run than threads with lower priorities. Higher priorities do not guarantee a specific amount of execution time for your thread, just that it is more likely to be chosen by the scheduler when compared to lower-priority threads.

당신이 만드는 모든 새 스레드와 연관된 기본 우선 순위가 있습니다. 실행하는 스레드를 결정할 때 커널의 스케줄링 알고리즘은 우선 순위가 높은 쓰레드가 낮은 우선 순위를 가진 스레드보다 실행 가능성이되는, 계정에 스레드 우선 순위를 사용합니다. 높은 우선 순위는 우선 순위가 낮은 스레드에 비해 스케줄러에 의해 선택 될 가능성이 높습니다 그냥 당신의 스레드에 대한 실행 시간의 특정 금액을 보장하지 않습니다.

If you do want to modify thread priorities, both Cocoa and POSIX provide a way to do so. For Cocoa threads, you can use the setThreadPriority: class method ofNSThread to set the priority of the currently running thread. For POSIX threads, you use the pthread_setschedparam function. For more information, seeNSThread Class Reference or pthread_setschedparam man page.

당신이 스레드 우선 순위를 변경하려는 경우, 코코아 및 POSIX 모두 그렇게 할 수있는 방법을 제공합니다. 코코아 스레드, 당신은 setThreadPriority을 사용할 수 있습니다 : 클래스 메소드 ofNSThread을 현재 실행중인 스레드의 우선 순위를 설정합니다. POSIX 쓰레드를 들어, 당신은 pthread_setschedparam 기능을 사용합니다. 자세한 내용은 seeNSThread 클래스 참조 또는 pthread_setschedparam 매뉴얼 페이지에 대한.

Writing Your Thread Entry Routine
귀하의 스레드 입력 루틴을 작성

For the most part, the structure of your thread’s entry point routines is the same in OS X as it is on other platforms. You initialize your data structures, do some work or optionally set up a run loop, and clean up when your thread’s code is done. Depending on your design, there may be some additional steps you need to take when writing your entry routine.

그것은 다른 플랫폼이기 때문에 대부분의 경우, 사용자 스레드의 진입 점 루틴의 구조는 OS X에서 동일합니다. 당신은 당신의 데이터 구조를 초기화하는 몇 가지 작업을 수행하거나 선택적으로 실행 루프를 설정하고 스레드의 코드가 완료되면 정리. 당신의 디자인에 따라, 당신은 항목 루틴을 작성할 때 취할 필요가 몇 가지 추가 단계가있을 수 있습니다.

Creating an Autorelease Pool

오토 릴리스 풀 만들기

Applications that link in Objective-C frameworks typically must create at least one autorelease pool in each of their threads. If an application uses the managed model—where the application handles the retaining and releasing of objects—the autorelease pool catches any objects that are autoreleased from that thread.

오브젝티브-C 프레임 워크에있는 링크는 일반적으로 해당 스레드 각각에 적어도 하나 autorelease를 풀을 만들어야합니다하는 응용 프로그램.응용 프로그램을 사용하는 경우 응용 프로그램의 유지 및 해제 처리 모델 위치 관리 객체를 autorelease를 풀 그 스레드에서 autoreleased 된 개체를 잡는다.

If an application uses garbage collection instead of the managed memory model, creation of an autorelease pool is not strictly necessary. The presence of an autorelease pool in a garbage-collected application is not harmful, and for the most part is simply ignored. It is allowed for cases where a code module must support both garbage collection and the managed memory model. In such a case, the autorelease pool must be present to support the managed memory model code and is simply ignored if the application is run with garbage collection enabled.

응용 프로그램이 대신 관리되는 메모리 모델의 가비지 수집을 사용하는 경우 autorelease를 풀의 생성은 꼭 필요하지 않습니다.가비지 수집 응용 프로그램에서 autorelease를 풀의 존재는 유해하지 않고, 대부분의 경우 단순히 무시됩니다. 이 코드 모듈 가비지 수집 및 관리되는 메모리 모델을 모두 지원해야하는 경우에 허용된다. 이러한 경우, autorelease를 풀은 관리되는 메모리 모델 코드를 지원하기 위해 존재해야하고 응용 프로그램을 사용할 가비지 컬렉션을 실행하면 간단하게 무시됩니다.

If your application uses the managed memory model, creating an autorelease pool should be the first thing you do in your thread entry routine. Similarly, destroying this autorelease pool should be the last thing you do in your thread. This pool ensures that autoreleased objects are caught, although it does not release them until the thread itself exits. Listing 2-2 shows the structure of a basic thread entry routine that uses an autorelease pool.

응용 프로그램이 작성, 관리되는 메모리 모델을 사용하는 경우 autorelease를 풀은 당신의 스레드 입력 루틴에서 할 첫 번째 일은해야한다. 마찬가지로,이 autorelease를 풀을 파괴하는 것은 당신의 스레드에서 수행 할 마지막 일이 될 것이다. 이 풀은 스레드 자체가 종료 될 때까지 해제되지 않지만 autoreleased 개체가 발견되어 있는지 확인합니다. 목록 2-2 autorelease를 풀을 사용하여 기본 스레드 입력 루틴의 구조를 보여줍니다.

Listing 2-2  Defining your thread entry point routine

- (void)myThreadMainRoutine
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // Top-level pool
 
    // Do thread work here.
 
    [pool release];  // Release the objects in the pool.
}

Because the top-level autorelease pool does not release its objects until the thread exits, long-lived threads should create additional autorelease pools to free objects more frequently. For example, a thread that uses a run loop might create and release an autorelease pool each time through that run loop. Releasing objects more frequently prevents your application’s memory footprint from growing too large, which can lead to performance problems. As with any performance-related behavior though, you should measure the actual performance of your code and tune your use of autorelease pools appropriately.

최상위 autorelease를 풀 스레드가 종료 될 때까지 해당 개체를 해제하지 않기 때문에, 수명이 긴 스레드가 더 자주 무료 오브젝트에 추가 autorelease를 풀을 만들어야합니다. 예를 들어, 실행 루프를 사용하여 스레드가 실행되는 루프를 통해 매번 생성하고 autorelease를 풀을 해제 할 수 있습니다. 객체를 해제하면 더 자주 성능 문제로 이어질 수있는, 너무 큰 성장에서 응용 프로그램의 메모리 풋 프린트를 방지 할 수 있습니다. 하지만 모든 성능 관련 문제와 마찬가지로, 당신은 당신의 코드의 실제 성능을 측정하고 적절하게 autorelease를 풀의 사용을 조정해야합니다.

For more information on memory management and autorelease pools, see Advanced Memory Management Programming Guide.
메모리 관리 및 autorelease를 풀에 대한 자세한 내용은 고급 메모리 관리 프로그래밍 가이드를 참조하십시오.

Setting Up an Exception Handler

예외 처리기를 설정

If your application catches and handles exceptions, your thread code should be prepared to catch any exceptions that might occur. Although it is best to handle exceptions at the point where they might occur, failure to catch a thrown exception in a thread causes your application to exit. Installing a final try/catch in your thread entry routine allows you to catch any unknown exceptions and provide an appropriate response.

응용 프로그램이 예외를 catch 및 처리하는 경우 스레드 코드가 발생할 수있는 모든 예외를 catch 할 준비가되어 있어야합니다. 그것은 그들이 발생할 수 있습니다 점에서 예외를 처리하는 것이 가장 좋지만, 스레드에서 throw 된 예외를 catch하지 못하면 응용 프로그램이 종료됩니다. 귀하의 스레드 진입 루틴에서 try / catch를 최종 설치를하면 알 수없는 예외를 catch하고 적절한 응답을 제공 할 수 있습니다.

You can use either the C++ or Objective-C exception handling style when building your project in Xcode. For information about setting how to raise and catch exceptions in Objective-C, see Exception Programming Topics.

엑스 코드에서 프로젝트를 빌드 할 때는 C + + 또는 목표-C 예외 처리 스타일을 사용할 수 있습니다. 인상 및 목표-C에서 예외를 잡아 예외 프로그래밍 항목을 참조하는 방법을 설정하는 방법에 대한 자세한 내용은 다음을 참조하십시오.

Setting Up a Run Loop

실행 루프를 설정

When writing code you want to run on a separate thread, you have two options. The first option is to write the code for a thread as one long task to be performed with little or no interruption, and have the thread exit when it finishes. The second option is put your thread into a loop and have it process requests dynamically as they arrive. The first option requires no special setup for your code; you just start doing the work you want to do. The second option, however, involves setting up your thread’s run loop.

당신이 별도의 스레드에서 실행하려면 코드를 작성할 때, 당신은 두 가지 옵션이 있습니다.첫 번째 옵션은 하나의 긴 작업이 거의 중단없이 수행 할 수로 스레드 코드를 작성하고 완료되면 스레드 종료하는 것입니다.두 번째 옵션은 루프로 스레드를 넣고 그들이 도착 동적으로 요청을 처리해야합니다.첫 번째 옵션은 코드에 대한 특별한 설정을 필요로하지 않습니다, ​​당신은 당신이하고 싶은 일을 시작합니다. 두 번째 옵션은, 그러나 스레드의 실행 루프를 설정하는 것과 관련되어 있습니다.

OS X and iOS provide built-in support for implementing run loops in every thread. The app frameworks start the run loop of your application’s main thread automatically. If you create any secondary threads, you must configure the run loop and start it manually.

OS X 및 IOS는 모든 스레드에서 실행 루프를 구현하기위한 기본적으로 지원합니다.응용 프로그램 프레임 워크가 자동으로 응용 프로그램의 주 스레드의 실행 루프를 시작합니다. 당신은 어떤 보조 스레드를 만들 경우 실행 루프를 구성하고 수동으로 시작해야합니다.

For information on using and configuring run loops, see “Run Loops.”
실행 루프를 사용 및 구성에 대한 자세한 내용은 "실행 루프"를 참조하십시오.

Terminating a Thread
스레드 종료

The recommended way to exit a thread is to let it exit its entry point routine normally. Although Cocoa, POSIX, and Multiprocessing Services offer routines for killing threads directly, the use of such routines is strongly discouraged. Killing a thread prevents that thread from cleaning up after itself. Memory allocated by the thread could potentially be leaked and any other resources currently in use by the thread might not be cleaned up properly, creating potential problems later.

스레드를 종료하기 위해 권장되는 방법은 일반적으로의 진입 점 루틴을 종료하도록하는 것입니다. 코코아, POSIX 및 멀티 프로세싱 서비스 직접 스레드를 죽이는 루틴을 제공하지만, 이러한 루틴의 사용을 강력하게 권장합니다.스레드를 죽이는 것은 자신 후에 청소에서 해당 스레드를 방지 할 수 있습니다.스레드에 의해 할당 된 메모리는 잠재적으로 유출 될 수있는 현재 스레드에서 사용하는 다른 자원은 나중에 잠재적 인 문제를 만들고 제대로 정리되지 않을 수 있습니다.

If you anticipate the need to terminate a thread in the middle of an operation, you should design your threads from the outset to respond to a cancel or exit message. For long-running operations, this might mean stopping work periodically and checking to see if such a message arrived. If a message does come in asking the thread to exit, the thread would then have the opportunity to perform any needed cleanup and exit gracefully; otherwise, it could simply go back to work and process the next chunk of data.

당신이 작업의 중간에 스레드를 종료 할 필요가 예상되는 경우, 당신은 취소에 응답하거나 메시지를 종료하려면 처음부터 당신의 스레드를 설계해야합니다. 장기 실행 작업의 경우,이 주기적으로 작업을 중지하고 메시지가 도착하는지 확인하는 검사를 의미 할 수 있습니다.메시지를 종료 할 스레드를 물어 올 경우, 스레드는 필요한 모든 정리 작업을 수행하고 정상적으로 종료 할 수있는 기회를 가질 것입니다, 그렇지 않으면 단순히 일하러 가서 데이터의 다음 청크를 처리 할 수 있습니다.

One way to respond to cancel messages is to use a run loop input source to receive such messages. Listing 2-3 shows the structure of how this code might look in your thread’s main entry routine. (The example shows the main loop portion only and does not include the steps for setting up an autorelease pool or configuring the actual work to do.) The example installs a custom input source on the run loop that presumably can be messaged from another one of your threads; for information on setting up input sources, see “Configuring Run Loop Sources.” After performing a portion of the total amount of work, the thread runs the run loop briefly to see if a message arrived on the input source. If not, the run loop exits immediately and the loop continues with the next chunk of work. Because the handler does not have direct access to the exitNow local variable, the exit condition is communicated through a key-value pair in the thread dictionary.

메시지를 취소하려면 대응하는 한 가지 방법은 메시지를 수신 런 루프 입력 소스를 사용하는 것입니다. 목록 2-3이 코드가 스레드의 주 진입 루틴에서 볼 수있는 방법의 구조를 보여줍니다. (예제는 메인 루프 부분을 보여줍니다 autorelease를 풀을 설정하거나 할 수있는 실제 작업을 구성하는 단계를 포함하지 않습니다.) 예제는 아마도 또 다른 하나의 메세지를 할 수있는 실행 루프에 사용자 정의 입력 소스를 설치 귀하의 스레드, 입력 소스를 설정하는 방법에 대한 자세한 내용은 "실행 루프 소스 구성"을 참조하십시오. 작업의 총 금액의 일부를 수행 한 후 스레드가 메시지가 입력 소스에 도착하는지 간단히 실행 루프를 실행합니다. 그렇지 않은 경우, 즉시 실행 루프가 종료되고 루프 작업의 다음 청크를 계속합니다. 핸들러가 exitNow 로컬 변수에 직접 액세스 할 수 없기 때문에, 종료 상태는 스레드 사전의 키 - 값 쌍을 통해 전달됩니다.

Listing 2-3  Checking for an exit condition during a long job

- (void)threadMainRoutine
{
    BOOL moreWorkToDo = YES;
    BOOL exitNow = NO;
    NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
 
    // Add the exitNow BOOL to the thread dictionary.
    NSMutableDictionary* threadDict = [[NSThread currentThread] threadDictionary];
    [threadDict setValue:[NSNumber numberWithBool:exitNow] forKey:@"ThreadShouldExitNow"];
 
    // Install an input source.
    [self myInstallCustomInputSource];
 
    while (moreWorkToDo && !exitNow)
    {
        // Do one chunk of a larger body of work here.
        // Change the value of the moreWorkToDo Boolean when done.
 
        // Run the run loop but timeout immediately if the input source isn't waiting to fire.
        [runLoop runUntilDate:[NSDate date]];
 
        // Check to see if an input source handler changed the exitNow value.
        exitNow = [[threadDict valueForKey:@"ThreadShouldExitNow"] boolValue];
    }
}

Posted by 창업자닉군
,