Если метод называют в то же самое время дважды, как только выполнить его однажды?

./ текущие каталог. Это - в основном то же как всего file.php, но во многих случаях (включенный) это не проверяет, что любой стандарт помещает, PHP мог бы искать файл, вместо этого проверяя только текущий каталог.

От документация PHP (замечают последнее предложение):

Файлы для включения сначала разыскиваются в каждой include_path записи относительно текущего рабочего каталога, и затем в каталоге текущего сценария. Например, если Ваш include_path является библиотеками, текущий рабочий каталог является/www/, Вы включали include/a.php и существует, включают "b.php" в тот файл, b.php сначала смотрят в/www/libraries/и затем в/www/include/. Если имя файла начинается с./или../, это смотрят только в текущем рабочем каталоге.

5
задан Jacob 5 October 2009 в 10:41
поделиться

8 ответов

One method is a BOOL member that you set when entering the method and clear on leaving it. If the variable is set upon entry, you know it's already executing and can just return.

Assuming you're being called from multiple threads, you'll want to lock access to this critical area of checking/setting. An NSLock is good for this.

The code below has two implementations: myMethod1 which uses NSLock and myMethod2 which shows using @synchronize.

@interface MyClass : NSObject
{
    NSLock* theLock;
    BOOL isRunning;
}
@end

@implementation MyClass

-(id)init
{
    self = [super init];
    if(self != nil)
    {
        theLock = [[NSLock alloc] init];
        isRunning = NO;
    }
    return self;
}

-(void)dealloc
{
    [theLock release];
    [super dealloc];
}

// Use NSLock to guard the critical areas
-(void)myMethod1
{
    [theLock lock];

    if(isRunning == YES)
    {
        [theLock unlock]; // Unlock before returning
        return;
    }

    isRunning = YES;        

    // Do fun stuff here

    isRunning = NO;

    [theLock unlock];    
}

// This method uses @synchronize
-(void)myMethod2
{
    @synchronized(self)
    {
        if(isRunning == YES)
        {
            return;
        }

        isRunning = YES;

        // Do stuff here.

        isRunning = NO;
    }
}
@end
10
ответ дан 18 December 2019 в 09:08
поделиться

Вау. Это правильный ответ, но он сильно переоценен. Просто используйте @synchronized () .

Foo.h:

@interface Foo
{
    id expensiveResult;
}
- (void) bar;
@end

Foo.m:

@implementation Foo
- (void) bar
{
    @synchronized(self) {
        if (expensiveResult) return expensiveResult;
        .... do expensive stuff here ....
        expensiveResult = [theResult retain];
    }
    return expensiveResult;
}
@end

Если у вас есть несколько экземпляров Foo и вы хотите гарантировать исключительность для всех экземпляров, создайте глобальную переменную в + (void) initialize - NSString подойдет - и @synchronized () по этому поводу.

Однако ваш вопрос поднимает гораздо более важный вопрос. В частности, Никогда не бывает случая, когда один и тот же метод будет вызываться дважды одновременно, если вы явно не настроили свое приложение так, чтобы именно это произошло.

Предоставленные ответы больше похожи на исправление симптома, а не на исправление реальной проблемы.

Примечание: это полагается на то, что RoadResult равен нулю, то есть при создании экземпляра все iVars равны нулю. Очевидно, сбросьте ivar на ноль, если вы хотите пересчитать.

5
ответ дан 18 December 2019 в 09:08
поделиться

Some of the given answers are acceptable solutions to the problem of multiple "producer" threads calling the same function at the same time but you might be better off figuring out why multiple threads are calling this same block of code at the same time. It could be that you are assigning this delegate to multiple event handlers or something like that. You have probably noticed that this is occurring because some shared state is being mangled or the output of the function is not correct for the "global" state at the end of the function. Putting a bandaid over the fact 2 threads are in a given function (when its clear that threading was not a primary concern when this was written) is not going to necessarily give you the right results. Threading is not trivial and shared state makes it very tricky to get right, make sure that you completely understand why this is occurring before just trying to patch over it.

That being said, if you do take the bandaid approach, its probably better to do one with a lock where every thread eventually gets to execute the function rather than having them bail out if the function is allready started because to the client code it would look like that long and "heavy-lifting" process has completed and they may check for the results.

2
ответ дан 18 December 2019 в 09:08
поделиться

If these calls are synchronized, so only one happens at a time, you can just have a variable on your class, called something like "initialized", which starts off false and is set when initialized:

if (!initialized) {
    // handle delegated call
    initialized = 1;
}

If the delegate is called from multiple threads, you need to put all this in a mutex block.

0
ответ дан 18 December 2019 в 09:08
поделиться

Use pthread_once() -- it was explicitly designed to do exactly this. The only problem is that the function you pass it can't take any arguments, so you have to use global variables to pass information to it.

0
ответ дан 18 December 2019 в 09:08
поделиться

Here's how you can use objective-c locks as mutexes.

http://rosettacode.org/wiki/Mutex#Objective-C

Mutexes exist to allow mutually exclusive access to a certain block of code. Within the method you can do something like:

[methodLock lock]; //Blocks and waits until the lock is released
//...do stuff
[methodLock unlock]; //Releases the lock once the code has executed.

This will ensure that only one thread will be allowed within the //do stuff block of code.

EDIT: I read the question again; within the lock I'd check the flag to see if it's run (using a BOOL)

0
ответ дан 18 December 2019 в 09:08
поделиться

Если они вызываются в одно и то же время, я полагаю, они вызываются в потоках?

Что вы можете сделать, это определить BOOL @property (например, называется isRunning ) с атрибутом atomic (установлен по умолчанию). Таким образом, к этому свойству можно будет безопасно обращаться из разных потоков, а затем вы можете сделать что-то вроде:

if (isRunning)
    return ;
isRunning = YES;
// ...
// Your code here
// ...
usRunning = NO;

Вы также можете убедиться, что делаете правильно. Если ваш метод вызывается дважды, возможно, вы что-то делаете не так (а может, это нормально, я не знаю, что вы делаете;))

-1
ответ дан 18 December 2019 в 09:08
поделиться

simplest is to set a flag.

- (void)action {
  if (flag_is_set == NO) {
    flag_is_set = YES;
    do stuff
    flag_is_set = NO;
  }
}

this is not 100% safe though as you may get some rare cases of interlocking.

If you can handle some sleeps on the thread, use a nslock

- (id)init {
  theLock = [[NSLock alloc] init];
}
- (void)action {
  [theLock lock];
  doStuff
  [theLock unlock];
}

When thread 2 comes to the lock call and thread 1 already has it, it will sit in the execution loop until the lock is released, then it will start again. If you have UI on this thread, you app will appear to freeze

2
ответ дан 18 December 2019 в 09:08
поделиться